diff options
1356 files changed, 15688 insertions, 13432 deletions
diff --git a/Android.bp b/Android.bp index 949373317097..b1eb4a5ff247 100644 --- a/Android.bp +++ b/Android.bp @@ -604,8 +604,9 @@ java_defaults { ], required: [ "framework-platform-compat-config", - // TODO: remove gps_debug and protolog.conf.json when the build system propagates "required" properly. + // TODO: remove gps_debug, cec_config.xml and protolog.conf.json when the build system propagates "required" properly. "gps_debug.conf", + "cec_config.xml", "icu4j-platform-compat-config", "libcore-platform-compat-config", "protolog.conf.json.gz", diff --git a/BATTERY_STATS_OWNERS b/BATTERY_STATS_OWNERS new file mode 100644 index 000000000000..7728975fcec1 --- /dev/null +++ b/BATTERY_STATS_OWNERS @@ -0,0 +1,4 @@ +# OWNERS of BatteryStats related files +bookatz@google.com +dplotnikov@google.com +mwachens@google.com diff --git a/OWNERS b/OWNERS new file mode 100644 index 000000000000..4f89f7dde6af --- /dev/null +++ b/OWNERS @@ -0,0 +1,24 @@ +# This top-level list should remain narrowly defined as team leads; individual +# teams are strongly encouraged to define narrower OWNERS files at deeper +# levels within the source tree; see OWNERS.md for more details +dsandler@android.com +dsandler@google.com +hackbod@android.com +hackbod@google.com +jsharkey@android.com +jsharkey@google.com +michaelwr@google.com +nandana@google.com +narayan@google.com +ogunwale@google.com +svetoslavganov@android.com +svetoslavganov@google.com +yamasani@google.com + +# Support bulk translation updates +per-file */res*/values*/*.xml = byi@google.com + +per-file Android.bp = file:platform/build/soong:/OWNERS +per-file Android.mk = file:platform/build/soong:/OWNERS +per-file ApiDocs.bp = file:platform/build/soong:/OWNERS +per-file StubLibraries.bp = file:platform/build/soong:/OWNERS diff --git a/OWNERS.md b/OWNERS.md new file mode 100644 index 000000000000..6428c59fd793 --- /dev/null +++ b/OWNERS.md @@ -0,0 +1,34 @@ +As general background, `OWNERS` files expedite code reviews by helping code +authors quickly find relevant reviewers, and they also ensure that stakeholders +are involved in code changes in their areas. + +The structure of `frameworks/base/` is unique among Android repositories, and +it's evolved into a complex interleaved structure over the years. Because of +this structure, the best place to authoritatively define `OWNERS` can vary +wildly, but here are some common patterns: + +* `core/java/` contains source that is included in the base classpath, and as +such it's where most APIs are defined: + * `core/java/android/app/` + * `core/java/android/content/` +* `services/core/` contains most system services, and these directories +typically have more granularity than `core/java/`, since they can be refactored +without API changes: + * `services/core/java/com/android/server/net/` + * `services/core/java/com/android/server/wm/` +* `services/` contains several system services that have been isolated from the +main `services/core/` project: + * `services/appwidget/` + * `services/midi/` +* `apex/` contains Mainline modules: + * `apex/jobscheduler/` + * `apex/permission/` +* Finally, some teams may have dedicated top-level directories: + * `media/` + * `wifi/` + +Area maintainers are strongly encouraged to list people in a single +authoritative `OWNERS` file in **exactly one** location. Then, other paths +should reference that single authoritative `OWNERS` file using an include +directive. This approach ensures that updates are applied consistently across +the tree, reducing maintenance burden. diff --git a/ZYGOTE_OWNERS b/ZYGOTE_OWNERS new file mode 100644 index 000000000000..90a185b79b52 --- /dev/null +++ b/ZYGOTE_OWNERS @@ -0,0 +1,5 @@ +calin@google.com +chriswailes@google.com +maco@google.com +narayan@google.com +ngeoffray@google.com diff --git a/apct-tests/perftests/OWNERS b/apct-tests/perftests/OWNERS new file mode 100644 index 000000000000..a060ad9a5a7e --- /dev/null +++ b/apct-tests/perftests/OWNERS @@ -0,0 +1,2 @@ +timmurray@google.com +philipcuadra@google.com diff --git a/apct-tests/perftests/autofill/OWNERS b/apct-tests/perftests/autofill/OWNERS new file mode 100644 index 000000000000..c52751d79227 --- /dev/null +++ b/apct-tests/perftests/autofill/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/autofill/OWNERS diff --git a/apct-tests/perftests/blobstore/OWNERS b/apct-tests/perftests/blobstore/OWNERS new file mode 100644 index 000000000000..65bb6b8a5423 --- /dev/null +++ b/apct-tests/perftests/blobstore/OWNERS @@ -0,0 +1 @@ +include /apex/blobstore/OWNERS diff --git a/apct-tests/perftests/contentcapture/OWNERS b/apct-tests/perftests/contentcapture/OWNERS new file mode 100644 index 000000000000..a28e00a5c490 --- /dev/null +++ b/apct-tests/perftests/contentcapture/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/contentcapture/OWNERS diff --git a/apct-tests/perftests/core/apps/overlay/OWNERS b/apct-tests/perftests/core/apps/overlay/OWNERS new file mode 100644 index 000000000000..afb98d416762 --- /dev/null +++ b/apct-tests/perftests/core/apps/overlay/OWNERS @@ -0,0 +1 @@ +include /core/java/android/content/om/OWNERS diff --git a/apct-tests/perftests/core/src/android/accounts/OWNERS b/apct-tests/perftests/core/src/android/accounts/OWNERS new file mode 100644 index 000000000000..df1b4f432cd6 --- /dev/null +++ b/apct-tests/perftests/core/src/android/accounts/OWNERS @@ -0,0 +1 @@ +include /core/java/android/accounts/OWNERS diff --git a/apct-tests/perftests/core/src/android/database/OWNERS b/apct-tests/perftests/core/src/android/database/OWNERS new file mode 100644 index 000000000000..bb9a2ca27ba9 --- /dev/null +++ b/apct-tests/perftests/core/src/android/database/OWNERS @@ -0,0 +1 @@ +include /core/java/android/database/OWNERS diff --git a/apct-tests/perftests/inputmethod/OWNERS b/apct-tests/perftests/inputmethod/OWNERS new file mode 100644 index 000000000000..5deb2ce8f24b --- /dev/null +++ b/apct-tests/perftests/inputmethod/OWNERS @@ -0,0 +1 @@ +include /core/java/android/view/inputmethod/OWNERS diff --git a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfRunPrecondition.java b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfRunPrecondition.java index fc48fd5271a8..4bfcadebc2d9 100644 --- a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfRunPrecondition.java +++ b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfRunPrecondition.java @@ -16,134 +16,8 @@ package android.inputmethod; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; -import static android.inputmethod.ImePerfTestBase.executeShellCommand; -import static android.inputmethod.ImePerfTestBase.runWithShellPermissionIdentity; - -import android.app.ActivityManager; -import android.app.ActivityManager.RunningAppProcessInfo; -import android.app.ActivityTaskManager; -import android.content.Context; -import android.inputmethod.ImePerfTestBase.SettingsSession; -import android.os.BatteryManager; -import android.os.Bundle; -import android.os.SystemClock; -import android.provider.Settings; -import android.util.Log; -import android.view.WindowManagerPolicyConstants; - -import androidx.test.platform.app.InstrumentationRegistry; - -import com.android.internal.policy.PhoneWindow; - -import org.junit.runner.Description; -import org.junit.runner.Result; -import org.junit.runner.notification.RunListener; - -import java.util.List; +import android.perftests.utils.WindowPerfRunPreconditionBase; /** Prepare the preconditions before running performance test. */ -public class ImePerfRunPrecondition extends RunListener { - private static final String TAG = ImePerfRunPrecondition.class.getSimpleName(); - - private static final String ARGUMENT_LOG_ONLY = "log"; - private static final String ARGUMENT_KILL_BACKGROUND = "kill-bg"; - private static final String ARGUMENT_PROFILING_ITERATIONS = "profiling-iterations"; - private static final String ARGUMENT_PROFILING_SAMPLING = "profiling-sampling"; - private static final String DEFAULT_PROFILING_ITERATIONS = "10"; - private static final String DEFAULT_PROFILING_SAMPLING_US = "10"; - private static final long KILL_BACKGROUND_WAIT_MS = 3000; - - /** The requested iterations to run with method profiling. */ - static int sProfilingIterations; - - /** The interval of sample profiling in microseconds. */ - static int sSamplingIntervalUs; - - private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext(); - private long mWaitPreconditionDoneMs = 500; - - private final SettingsSession<Integer> mStayOnWhilePluggedInSetting = new SettingsSession<>( - Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0), - value -> executeShellCommand(String.format("settings put global %s %d", - Settings.Global.STAY_ON_WHILE_PLUGGED_IN, value))); - - private final SettingsSession<Integer> mNavigationModeSetting = new SettingsSession<>( - mContext.getResources().getInteger( - com.android.internal.R.integer.config_navBarInteractionMode), - value -> { - final String navOverlay; - switch (value) { - case WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL: - default: - navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY; - break; - } - executeShellCommand("cmd overlay enable-exclusive " + navOverlay); - }); - - /** It only executes once before all tests. */ - @Override - public void testRunStarted(Description description) { - final Bundle arguments = InstrumentationRegistry.getArguments(); - // If true, it only logs the method names without running. - final boolean skip = Boolean.parseBoolean(arguments.getString(ARGUMENT_LOG_ONLY, "false")); - Log.i(TAG, "arguments=" + arguments); - if (skip) { - return; - } - sProfilingIterations = Integer.parseInt( - arguments.getString(ARGUMENT_PROFILING_ITERATIONS, DEFAULT_PROFILING_ITERATIONS)); - sSamplingIntervalUs = Integer.parseInt( - arguments.getString(ARGUMENT_PROFILING_SAMPLING, DEFAULT_PROFILING_SAMPLING_US)); - - // Use same navigation mode (gesture navigation) across all devices and tests - // for consistency. - mNavigationModeSetting.set(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL); - // Keep the device awake during testing. - mStayOnWhilePluggedInSetting.set(BatteryManager.BATTERY_PLUGGED_ANY); - - runWithShellPermissionIdentity(() -> { - final ActivityTaskManager atm = mContext.getSystemService(ActivityTaskManager.class); - atm.removeAllVisibleRecentTasks(); - atm.removeRootTasksWithActivityTypes(new int[] { ACTIVITY_TYPE_STANDARD, - ACTIVITY_TYPE_ASSISTANT, ACTIVITY_TYPE_RECENTS, ACTIVITY_TYPE_UNDEFINED }); - }); - PhoneWindow.sendCloseSystemWindows(mContext, "ImePerfTests"); - - if (Boolean.parseBoolean(arguments.getString(ARGUMENT_KILL_BACKGROUND))) { - runWithShellPermissionIdentity(this::killBackgroundProcesses); - mWaitPreconditionDoneMs = KILL_BACKGROUND_WAIT_MS; - } - // Wait a while for the precondition setup to complete. - SystemClock.sleep(mWaitPreconditionDoneMs); - } - - private void killBackgroundProcesses() { - Log.i(TAG, "Killing background processes..."); - final ActivityManager am = mContext.getSystemService(ActivityManager.class); - final List<RunningAppProcessInfo> processes = am.getRunningAppProcesses(); - if (processes == null) { - return; - } - for (RunningAppProcessInfo processInfo : processes) { - if (processInfo.importanceReasonCode == RunningAppProcessInfo.REASON_UNKNOWN - && processInfo.importance > RunningAppProcessInfo.IMPORTANCE_SERVICE) { - for (String pkg : processInfo.pkgList) { - am.forceStopPackage(pkg); - } - } - } - } - - /** It only executes once after all tests. */ - @Override - public void testRunFinished(Result result) { - mNavigationModeSetting.close(); - mStayOnWhilePluggedInSetting.close(); - } +public class ImePerfRunPrecondition extends WindowPerfRunPreconditionBase { } diff --git a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java index 2b7af2f0a11e..689fb3645daf 100644 --- a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java +++ b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java @@ -29,7 +29,6 @@ import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.inputmethodservice.InputMethodService; -import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.SystemClock; import android.perftests.utils.ManualBenchmarkState; @@ -420,23 +419,20 @@ public class ImePerfTest extends ImePerfTestBase }); } - private void startAsyncAtrace() throws IOException { + private void startAsyncAtrace() { mIsTraceStarted = true; // IMF uses 'wm' component for trace in InputMethodService, InputMethodManagerService, // WindowManagerService and 'view' for client window (InsetsController). // TODO(b/167947940): Consider a separate input_method atrace - UI_AUTOMATION.executeShellCommand("atrace -b 32768 --async_start wm view"); - // Avoid atrace isn't ready immediately. - SystemClock.sleep(TimeUnit.NANOSECONDS.toMillis(TIME_1_S_IN_NS)); + startAsyncAtrace("wm view"); } private void stopAsyncAtrace() { if (!mIsTraceStarted) { return; } - final ParcelFileDescriptor pfd = UI_AUTOMATION.executeShellCommand("atrace --async_stop"); mIsTraceStarted = false; - final InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(pfd); + final InputStream inputStream = stopAsyncAtraceWithStream(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { String line; while ((line = reader.readLine()) != null) { diff --git a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTestBase.java b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTestBase.java index 1a861d7ba87b..f70d79cf9153 100644 --- a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTestBase.java +++ b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTestBase.java @@ -18,135 +18,21 @@ package android.inputmethod; import static android.perftests.utils.PerfTestActivity.INTENT_EXTRA_ADD_EDIT_TEXT; -import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; - -import android.app.KeyguardManager; -import android.app.UiAutomation; -import android.content.Context; import android.content.Intent; -import android.os.ParcelFileDescriptor; -import android.os.PowerManager; import android.perftests.utils.PerfTestActivity; +import android.perftests.utils.WindowPerfTestBase; - -import androidx.test.rule.ActivityTestRule; - -import org.junit.BeforeClass; - -import java.io.ByteArrayOutputStream; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Objects; -import java.util.function.Consumer; - -public class ImePerfTestBase { - static final UiAutomation UI_AUTOMATION = getInstrumentation().getUiAutomation(); - static final long NANOS_PER_S = 1000L * 1000 * 1000; - static final long TIME_1_S_IN_NS = 1 * NANOS_PER_S; +public class ImePerfTestBase extends WindowPerfTestBase { static final long TIMEOUT_1_S_IN_MS = 1 * 1000L; - @BeforeClass - public static void setUpOnce() { - final Context context = getInstrumentation().getContext(); - - if (!context.getSystemService(PowerManager.class).isInteractive() - || context.getSystemService(KeyguardManager.class).isKeyguardLocked()) { - executeShellCommand("input keyevent KEYCODE_WAKEUP"); - executeShellCommand("wm dismiss-keyguard"); - } - context.startActivity(new Intent(Intent.ACTION_MAIN) - .addCategory(Intent.CATEGORY_HOME).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); - } - - /** - * Executes shell command with reading the output. It may also used to block until the current - * command is completed. - */ - static ByteArrayOutputStream executeShellCommand(String command) { - final ParcelFileDescriptor pfd = UI_AUTOMATION.executeShellCommand(command); - final byte[] buf = new byte[512]; - final ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - int bytesRead; - try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) { - while ((bytesRead = fis.read(buf)) != -1) { - bytes.write(buf, 0, bytesRead); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - return bytes; - } - - /** Returns how many iterations should run with method tracing. */ - static int getProfilingIterations() { - return ImePerfRunPrecondition.sProfilingIterations; - } - - static void runWithShellPermissionIdentity(Runnable runnable) { - UI_AUTOMATION.adoptShellPermissionIdentity(); - try { - runnable.run(); - } finally { - UI_AUTOMATION.dropShellPermissionIdentity(); - } - } - - static class SettingsSession<T> implements AutoCloseable { - private final Consumer<T> mSetter; - private final T mOriginalValue; - private boolean mChanged; - - SettingsSession(T originalValue, Consumer<T> setter) { - mOriginalValue = originalValue; - mSetter = setter; - } - - void set(T value) { - if (Objects.equals(value, mOriginalValue)) { - mChanged = false; - return; - } - mSetter.accept(value); - mChanged = true; - } - - @Override - public void close() { - if (mChanged) { - mSetter.accept(mOriginalValue); - } - } - } - - /** - * Provides an activity that keeps screen on and is able to wait for a stable lifecycle stage. - */ - static class PerfTestActivityRule extends ActivityTestRule<PerfTestActivity> { - private final Intent mStartIntent = - new Intent(getInstrumentation().getTargetContext(), PerfTestActivity.class); - - PerfTestActivityRule() { - this(false /* launchActivity */); - } - - PerfTestActivityRule(boolean launchActivity) { - super(PerfTestActivity.class, false /* initialTouchMode */, launchActivity); - } - - @Override - protected Intent getActivityIntent() { - return mStartIntent; - } + /** Provides an activity that contains an edit text view.*/ + static class PerfTestActivityRule extends PerfTestActivityRuleBase { @Override public PerfTestActivity launchActivity(Intent intent) { intent.putExtra(INTENT_EXTRA_ADD_EDIT_TEXT, true); return super.launchActivity(intent); } - - PerfTestActivity launchActivity() { - return launchActivity(mStartIntent); - } } static String[] buildArray(String[]... arrays) { diff --git a/apct-tests/perftests/packagemanager/OWNERS b/apct-tests/perftests/packagemanager/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/apct-tests/perftests/packagemanager/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/apct-tests/perftests/textclassifier/OWNERS b/apct-tests/perftests/textclassifier/OWNERS new file mode 100644 index 000000000000..46b3cb8824a0 --- /dev/null +++ b/apct-tests/perftests/textclassifier/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/textclassifier/OWNERS diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfRunPreconditionBase.java b/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfRunPreconditionBase.java new file mode 100644 index 000000000000..8d2ac0276592 --- /dev/null +++ b/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfRunPreconditionBase.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.perftests.utils; + +import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.perftests.utils.WindowPerfTestBase.executeShellCommand; +import static android.perftests.utils.WindowPerfTestBase.runWithShellPermissionIdentity; + +import android.app.ActivityManager; +import android.app.ActivityManager.RunningAppProcessInfo; +import android.app.ActivityTaskManager; +import android.content.Context; +import android.os.BatteryManager; +import android.os.Bundle; +import android.os.SystemClock; +import android.perftests.utils.WindowPerfTestBase.SettingsSession; +import android.provider.Settings; +import android.util.Log; +import android.view.WindowManagerPolicyConstants; + +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.internal.policy.PhoneWindow; + +import org.junit.runner.Description; +import org.junit.runner.Result; +import org.junit.runner.notification.RunListener; + +import java.util.List; + +/** Prepare the preconditions before running performance test. */ +public class WindowPerfRunPreconditionBase extends RunListener { + protected final String mTag = getClass().getSimpleName(); + + private static final String ARGUMENT_LOG_ONLY = "log"; + private static final String ARGUMENT_KILL_BACKGROUND = "kill-bg"; + private static final String ARGUMENT_PROFILING_ITERATIONS = "profiling-iterations"; + private static final String ARGUMENT_PROFILING_SAMPLING = "profiling-sampling"; + private static final String DEFAULT_PROFILING_ITERATIONS = "0"; + private static final String DEFAULT_PROFILING_SAMPLING_US = "10"; + private static final long KILL_BACKGROUND_WAIT_MS = 3000; + + /** The requested iterations to run with method profiling. */ + static int sProfilingIterations; + + /** The interval of sample profiling in microseconds. */ + static int sSamplingIntervalUs; + + private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext(); + private long mWaitPreconditionDoneMs = 500; + + private final SettingsSession<Integer> mStayOnWhilePluggedInSetting = new SettingsSession<>( + Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0), + value -> executeShellCommand(String.format("settings put global %s %d", + Settings.Global.STAY_ON_WHILE_PLUGGED_IN, value))); + + private final SettingsSession<Integer> mNavigationModeSetting = new SettingsSession<>( + mContext.getResources().getInteger( + com.android.internal.R.integer.config_navBarInteractionMode), + value -> { + final String navOverlay; + switch (value) { + case WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON: + navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY; + break; + case WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON: + navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY; + break; + case WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL: + default: + navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY; + break; + } + executeShellCommand("cmd overlay enable-exclusive " + navOverlay); + }); + + /** It only executes once before all tests. */ + @Override + public void testRunStarted(Description description) { + final Bundle arguments = InstrumentationRegistry.getArguments(); + // If true, it only logs the method names without running. + final boolean skip = Boolean.parseBoolean(arguments.getString(ARGUMENT_LOG_ONLY, "false")); + Log.i(mTag, "arguments=" + arguments); + if (skip) { + return; + } + sProfilingIterations = Integer.parseInt( + arguments.getString(ARGUMENT_PROFILING_ITERATIONS, DEFAULT_PROFILING_ITERATIONS)); + sSamplingIntervalUs = Integer.parseInt( + arguments.getString(ARGUMENT_PROFILING_SAMPLING, DEFAULT_PROFILING_SAMPLING_US)); + + // Use same navigation mode (gesture navigation) across all devices and tests + // for consistency. + mNavigationModeSetting.set(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL); + // Keep the device awake during testing. + mStayOnWhilePluggedInSetting.set(BatteryManager.BATTERY_PLUGGED_ANY); + + runWithShellPermissionIdentity(() -> { + final ActivityTaskManager atm = mContext.getSystemService(ActivityTaskManager.class); + atm.removeAllVisibleRecentTasks(); + atm.removeRootTasksWithActivityTypes(new int[] { ACTIVITY_TYPE_STANDARD, + ACTIVITY_TYPE_ASSISTANT, ACTIVITY_TYPE_RECENTS, ACTIVITY_TYPE_UNDEFINED }); + }); + PhoneWindow.sendCloseSystemWindows(mContext, mTag); + + if (Boolean.parseBoolean(arguments.getString(ARGUMENT_KILL_BACKGROUND))) { + runWithShellPermissionIdentity(this::killBackgroundProcesses); + mWaitPreconditionDoneMs = KILL_BACKGROUND_WAIT_MS; + } + // Wait a while for the precondition setup to complete. + SystemClock.sleep(mWaitPreconditionDoneMs); + } + + private void killBackgroundProcesses() { + Log.i(mTag, "Killing background processes..."); + final ActivityManager am = mContext.getSystemService(ActivityManager.class); + final List<RunningAppProcessInfo> processes = am.getRunningAppProcesses(); + if (processes == null) { + return; + } + for (RunningAppProcessInfo processInfo : processes) { + if (processInfo.importanceReasonCode == RunningAppProcessInfo.REASON_UNKNOWN + && processInfo.importance > RunningAppProcessInfo.IMPORTANCE_SERVICE) { + for (String pkg : processInfo.pkgList) { + am.forceStopPackage(pkg); + } + } + } + } + + /** It only executes once after all tests. */ + @Override + public void testRunFinished(Result result) { + mNavigationModeSetting.close(); + mStayOnWhilePluggedInSetting.close(); + } +} diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfTestBase.java b/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfTestBase.java new file mode 100644 index 000000000000..ca5913701d3b --- /dev/null +++ b/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfTestBase.java @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.perftests.utils; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import android.app.KeyguardManager; +import android.app.UiAutomation; +import android.content.Context; +import android.content.Intent; +import android.os.ParcelFileDescriptor; +import android.os.PowerManager; +import android.os.SystemClock; + +import androidx.test.rule.ActivityTestRule; + +import org.junit.After; +import org.junit.BeforeClass; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Objects; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +/** The base class for window related performance tests. */ +public class WindowPerfTestBase { + public static final long NANOS_PER_S = 1000L * 1000 * 1000; + public static final long TIME_1_S_IN_NS = 1 * NANOS_PER_S; + + static boolean sIsProfilingMethod; + + @BeforeClass + public static void setUpOnce() { + final Context context = getInstrumentation().getContext(); + + if (!context.getSystemService(PowerManager.class).isInteractive() + || context.getSystemService(KeyguardManager.class).isKeyguardLocked()) { + executeShellCommand("input keyevent KEYCODE_WAKEUP"); + executeShellCommand("wm dismiss-keyguard"); + } + context.startActivity(new Intent(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_HOME).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } + + @After + public void tearDown() { + // Make sure that profiling is stopped if test fails. + if (sIsProfilingMethod) { + stopProfiling(); + } + } + + public static UiAutomation getUiAutomation() { + return getInstrumentation().getUiAutomation(); + } + + public static void startAsyncAtrace(String tags) { + getUiAutomation().executeShellCommand("atrace -b 32768 --async_start " + tags); + // Avoid atrace isn't ready immediately. + SystemClock.sleep(TimeUnit.NANOSECONDS.toMillis(TIME_1_S_IN_NS)); + } + + public static InputStream stopAsyncAtraceWithStream() { + return new ParcelFileDescriptor.AutoCloseInputStream( + getUiAutomation().executeShellCommand("atrace --async_stop")); + } + + /** Starts method tracing on system server. */ + public static void startProfiling(File basePath, String outFileName) { + if (!basePath.exists()) { + executeShellCommand("mkdir -p " + basePath); + } + final String samplingArg = WindowPerfRunPreconditionBase.sSamplingIntervalUs > 0 + ? ("--sampling " + WindowPerfRunPreconditionBase.sSamplingIntervalUs) + : ""; + executeShellCommand("am profile start " + samplingArg + " system " + + new File(basePath, outFileName)); + sIsProfilingMethod = true; + } + + /** Stops method tracing of system server. */ + public static void stopProfiling() { + executeShellCommand("am profile stop system"); + sIsProfilingMethod = false; + } + + public static boolean sIsProfilingMethod() { + return sIsProfilingMethod; + } + + /** Returns how many iterations should run with method tracing. */ + public static int getProfilingIterations() { + return WindowPerfRunPreconditionBase.sProfilingIterations; + } + + /** + * Executes shell command with reading the output. It may also used to block until the current + * command is completed. + */ + public static ByteArrayOutputStream executeShellCommand(String command) { + final ParcelFileDescriptor pfd = getUiAutomation().executeShellCommand(command); + final byte[] buf = new byte[512]; + final ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + int bytesRead; + try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) { + while ((bytesRead = fis.read(buf)) != -1) { + bytes.write(buf, 0, bytesRead); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + return bytes; + } + + public static void runWithShellPermissionIdentity(Runnable runnable) { + getUiAutomation().adoptShellPermissionIdentity(); + try { + runnable.run(); + } finally { + getUiAutomation().dropShellPermissionIdentity(); + } + } + + public static class SettingsSession<T> implements AutoCloseable { + private final Consumer<T> mSetter; + private final T mOriginalValue; + private boolean mChanged; + + public SettingsSession(T originalValue, Consumer<T> setter) { + mOriginalValue = originalValue; + mSetter = setter; + } + + public void set(T value) { + if (Objects.equals(value, mOriginalValue)) { + mChanged = false; + return; + } + mSetter.accept(value); + mChanged = true; + } + + @Override + public void close() { + if (mChanged) { + mSetter.accept(mOriginalValue); + } + } + } + + /** + * Provides the {@link PerfTestActivity} with an associated customizable intent. + */ + public static class PerfTestActivityRuleBase extends ActivityTestRule<PerfTestActivity> { + protected final Intent mStartIntent = + new Intent(getInstrumentation().getTargetContext(), PerfTestActivity.class); + + public PerfTestActivityRuleBase() { + this(false /* launchActivity */); + } + + public PerfTestActivityRuleBase(boolean launchActivity) { + super(PerfTestActivity.class, false /* initialTouchMode */, launchActivity); + } + + @Override + public Intent getActivityIntent() { + return mStartIntent; + } + + public PerfTestActivity launchActivity() { + return launchActivity(mStartIntent); + } + } +} diff --git a/apct-tests/perftests/windowmanager/OWNERS b/apct-tests/perftests/windowmanager/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/apct-tests/perftests/windowmanager/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/apct-tests/perftests/windowmanager/src/android/wm/InternalWindowOperationPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/InternalWindowOperationPerfTest.java index 5c09ec2e760f..bccef533be32 100644 --- a/apct-tests/perftests/windowmanager/src/android/wm/InternalWindowOperationPerfTest.java +++ b/apct-tests/perftests/windowmanager/src/android/wm/InternalWindowOperationPerfTest.java @@ -18,7 +18,6 @@ package android.wm; import static android.perftests.utils.ManualBenchmarkState.StatsReport; -import android.os.ParcelFileDescriptor; import android.os.SystemClock; import android.perftests.utils.ManualBenchmarkState; import android.perftests.utils.ManualBenchmarkState.ManualBenchmarkTest; @@ -37,7 +36,6 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.util.concurrent.TimeUnit; /** Measure the performance of internal methods in window manager service by trace tag. */ @LargeTest @@ -85,7 +83,7 @@ public class InternalWindowOperationPerfTest extends WindowManagerPerfTestBase while (state.keepRunning(measuredTimeNs)) { if (!mIsTraceStarted && !mIsProfiling && !state.isWarmingUp()) { - startAsyncAtrace(); + startAsyncAtrace("wm"); mIsTraceStarted = true; } final long startTime = SystemClock.elapsedRealtimeNanos(); @@ -108,15 +106,8 @@ public class InternalWindowOperationPerfTest extends WindowManagerPerfTestBase Log.i(TAG, String.valueOf(mTraceMarkParser)); } - private void startAsyncAtrace() throws IOException { - sUiAutomation.executeShellCommand("atrace -b 32768 --async_start wm"); - // Avoid atrace isn't ready immediately. - SystemClock.sleep(TimeUnit.NANOSECONDS.toMillis(TIME_1_S_IN_NS)); - } - private void stopAsyncAtrace() { - final ParcelFileDescriptor pfd = sUiAutomation.executeShellCommand("atrace --async_stop"); - final InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(pfd); + final InputStream inputStream = stopAsyncAtraceWithStream(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { String line; while ((line = reader.readLine()) != null) { diff --git a/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java index 833cc0ff37a0..2aea61f4e540 100644 --- a/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java +++ b/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java @@ -96,7 +96,7 @@ public class RecentsAnimationPerfTest extends WindowManagerPerfTestBase @BeforeClass public static void setUpClass() { // Get the permission to invoke startRecentsActivity. - sUiAutomation.adoptShellPermissionIdentity(); + getUiAutomation().adoptShellPermissionIdentity(); final Context context = getInstrumentation().getContext(); final PackageManager pm = context.getPackageManager(); @@ -129,7 +129,7 @@ public class RecentsAnimationPerfTest extends WindowManagerPerfTestBase ActivityManager.resumeAppSwitches(); } catch (RemoteException ignored) { } - sUiAutomation.dropShellPermissionIdentity(); + getUiAutomation().dropShellPermissionIdentity(); } @Before @@ -233,7 +233,7 @@ public class RecentsAnimationPerfTest extends WindowManagerPerfTestBase // Ensure the animation callback is done. Assume.assumeTrue(recentsSemaphore.tryAcquire( - sIsProfilingMethod ? 10 * TIME_5_S_IN_NS : TIME_5_S_IN_NS, + sIsProfilingMethod() ? 10 * TIME_5_S_IN_NS : TIME_5_S_IN_NS, TimeUnit.NANOSECONDS)); } } diff --git a/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java index 29606030a041..9403e8b72348 100644 --- a/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java +++ b/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java @@ -54,12 +54,12 @@ public class WindowAddRemovePerfTest extends WindowManagerPerfTestBase @BeforeClass public static void setUpClass() { // Get the permission to use most window types. - sUiAutomation.adoptShellPermissionIdentity(); + getUiAutomation().adoptShellPermissionIdentity(); } @AfterClass public static void tearDownClass() { - sUiAutomation.dropShellPermissionIdentity(); + getUiAutomation().dropShellPermissionIdentity(); } /** The last customized iterations will provide the information of method profiling. */ diff --git a/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java b/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java index b51a9a8fb0dd..4b1982f60092 100644 --- a/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java +++ b/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java @@ -19,36 +19,21 @@ package android.wm; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import android.app.Activity; -import android.app.KeyguardManager; -import android.app.UiAutomation; -import android.content.Context; import android.content.Intent; -import android.os.ParcelFileDescriptor; -import android.os.PowerManager; import android.perftests.utils.PerfTestActivity; +import android.perftests.utils.WindowPerfTestBase; -import androidx.test.rule.ActivityTestRule; import androidx.test.runner.lifecycle.ActivityLifecycleCallback; import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry; import androidx.test.runner.lifecycle.Stage; -import org.junit.After; -import org.junit.BeforeClass; import org.junit.runner.Description; import org.junit.runners.model.Statement; -import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Objects; import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; -public class WindowManagerPerfTestBase { - static final UiAutomation sUiAutomation = getInstrumentation().getUiAutomation(); - static final long NANOS_PER_S = 1000L * 1000 * 1000; - static final long TIME_1_S_IN_NS = 1 * NANOS_PER_S; +public class WindowManagerPerfTestBase extends WindowPerfTestBase { static final long TIME_5_S_IN_NS = 5 * NANOS_PER_S; /** @@ -58,121 +43,21 @@ public class WindowManagerPerfTestBase { */ static final File BASE_OUT_PATH = new File("/data/local/tmp/WmPerfTests"); - static boolean sIsProfilingMethod; - - @BeforeClass - public static void setUpOnce() { - final Context context = getInstrumentation().getContext(); - - if (!context.getSystemService(PowerManager.class).isInteractive() - || context.getSystemService(KeyguardManager.class).isKeyguardLocked()) { - executeShellCommand("input keyevent KEYCODE_WAKEUP"); - executeShellCommand("wm dismiss-keyguard"); - } - context.startActivity(new Intent(Intent.ACTION_MAIN) - .addCategory(Intent.CATEGORY_HOME).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); - } - - @After - public void tearDown() { - // Make sure that profiling is stopped if test fails. - if (sIsProfilingMethod) { - stopProfiling(); - } + static void startProfiling(String outFileName) { + startProfiling(BASE_OUT_PATH, outFileName); } /** - * Executes shell command with reading the output. It may also used to block until the current - * command is completed. + * Provides an activity that is able to wait for a stable lifecycle stage. */ - static ByteArrayOutputStream executeShellCommand(String command) { - final ParcelFileDescriptor pfd = sUiAutomation.executeShellCommand(command); - final byte[] buf = new byte[512]; - final ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - int bytesRead; - try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) { - while ((bytesRead = fis.read(buf)) != -1) { - bytes.write(buf, 0, bytesRead); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - return bytes; - } - - /** Starts method tracing on system server. */ - static void startProfiling(String subPath) { - if (!BASE_OUT_PATH.exists()) { - executeShellCommand("mkdir -p " + BASE_OUT_PATH); - } - final String samplingArg = WmPerfRunListener.sSamplingIntervalUs > 0 - ? ("--sampling " + WmPerfRunListener.sSamplingIntervalUs) - : ""; - executeShellCommand("am profile start " + samplingArg + " system " - + new File(BASE_OUT_PATH, subPath)); - sIsProfilingMethod = true; - } - - static void stopProfiling() { - executeShellCommand("am profile stop system"); - sIsProfilingMethod = false; - } - - /** Returns how many iterations should run with method tracing. */ - static int getProfilingIterations() { - return WmPerfRunListener.sProfilingIterations; - } - - static void runWithShellPermissionIdentity(Runnable runnable) { - sUiAutomation.adoptShellPermissionIdentity(); - try { - runnable.run(); - } finally { - sUiAutomation.dropShellPermissionIdentity(); - } - } - - static class SettingsSession<T> implements AutoCloseable { - private final Consumer<T> mSetter; - private final T mOriginalValue; - private boolean mChanged; - - SettingsSession(T originalValue, Consumer<T> setter) { - mOriginalValue = originalValue; - mSetter = setter; - } - - void set(T value) { - if (Objects.equals(value, mOriginalValue)) { - mChanged = false; - return; - } - mSetter.accept(value); - mChanged = true; - } - - @Override - public void close() { - if (mChanged) { - mSetter.accept(mOriginalValue); - } - } - } - - /** - * Provides an activity that keeps screen on and is able to wait for a stable lifecycle stage. - */ - static class PerfTestActivityRule extends ActivityTestRule<PerfTestActivity> { - private final Intent mStartIntent = - new Intent(getInstrumentation().getTargetContext(), PerfTestActivity.class); + static class PerfTestActivityRule extends PerfTestActivityRuleBase { private final LifecycleListener mLifecycleListener = new LifecycleListener(); PerfTestActivityRule() { - this(false /* launchActivity */); } PerfTestActivityRule(boolean launchActivity) { - super(PerfTestActivity.class, false /* initialTouchMode */, launchActivity); + super(launchActivity); } @Override @@ -191,21 +76,12 @@ public class WindowManagerPerfTestBase { } @Override - protected Intent getActivityIntent() { - return mStartIntent; - } - - @Override public PerfTestActivity launchActivity(Intent intent) { final PerfTestActivity activity = super.launchActivity(intent); mLifecycleListener.setTargetActivity(activity); return activity; } - PerfTestActivity launchActivity() { - return launchActivity(mStartIntent); - } - void waitForIdleSync(Stage state) { mLifecycleListener.waitForIdleSync(state); } diff --git a/apct-tests/perftests/windowmanager/src/android/wm/WmPerfRunListener.java b/apct-tests/perftests/windowmanager/src/android/wm/WmPerfRunListener.java index a9d57167f6d2..2b0801af12cb 100644 --- a/apct-tests/perftests/windowmanager/src/android/wm/WmPerfRunListener.java +++ b/apct-tests/perftests/windowmanager/src/android/wm/WmPerfRunListener.java @@ -16,138 +16,8 @@ package android.wm; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; -import static android.wm.WindowManagerPerfTestBase.executeShellCommand; -import static android.wm.WindowManagerPerfTestBase.runWithShellPermissionIdentity; - -import android.app.ActivityManager; -import android.app.ActivityManager.RunningAppProcessInfo; -import android.app.ActivityTaskManager; -import android.content.Context; -import android.os.BatteryManager; -import android.os.Bundle; -import android.os.SystemClock; -import android.provider.Settings; -import android.util.Log; -import android.view.WindowManagerPolicyConstants; -import android.wm.WindowManagerPerfTestBase.SettingsSession; - -import androidx.test.platform.app.InstrumentationRegistry; - -import com.android.internal.policy.PhoneWindow; - -import org.junit.runner.Description; -import org.junit.runner.Result; -import org.junit.runner.notification.RunListener; - -import java.util.List; +import android.perftests.utils.WindowPerfRunPreconditionBase; /** Prepare the preconditions before running performance test. */ -public class WmPerfRunListener extends RunListener { - private static final String TAG = WmPerfRunListener.class.getSimpleName(); - - private static final String ARGUMENT_LOG_ONLY = "log"; - private static final String ARGUMENT_KILL_BACKGROUND = "kill-bg"; - private static final String ARGUMENT_PROFILING_ITERATIONS = "profiling-iterations"; - private static final String ARGUMENT_PROFILING_SAMPLING = "profiling-sampling"; - private static final String DEFAULT_PROFILING_ITERATIONS = "0"; - private static final String DEFAULT_PROFILING_SAMPLING_US = "10"; - private static final long KILL_BACKGROUND_WAIT_MS = 3000; - - /** The requested iterations to run with method profiling. */ - static int sProfilingIterations; - - /** The interval of sample profiling in microseconds. */ - static int sSamplingIntervalUs; - - private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext(); - private long mWaitPreconditionDoneMs = 500; - - private final SettingsSession<Integer> mStayOnWhilePluggedInSetting = new SettingsSession<>( - Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0), - value -> executeShellCommand(String.format("settings put global %s %d", - Settings.Global.STAY_ON_WHILE_PLUGGED_IN, value))); - - private final SettingsSession<Integer> mNavigationModeSetting = new SettingsSession<>( - mContext.getResources().getInteger( - com.android.internal.R.integer.config_navBarInteractionMode), - value -> { - final String navOverlay; - switch (value) { - case WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON: - navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY; - break; - case WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON: - navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY; - break; - case WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL: - default: - navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY; - break; - } - executeShellCommand("cmd overlay enable-exclusive " + navOverlay); - }); - - /** It only executes once before all tests. */ - @Override - public void testRunStarted(Description description) { - final Bundle arguments = InstrumentationRegistry.getArguments(); - // If true, it only logs the method names without running. - final boolean skip = Boolean.parseBoolean(arguments.getString(ARGUMENT_LOG_ONLY, "false")); - Log.i(TAG, "arguments=" + arguments); - if (skip) { - return; - } - sProfilingIterations = Integer.parseInt( - arguments.getString(ARGUMENT_PROFILING_ITERATIONS, DEFAULT_PROFILING_ITERATIONS)); - sSamplingIntervalUs = Integer.parseInt( - arguments.getString(ARGUMENT_PROFILING_SAMPLING, DEFAULT_PROFILING_SAMPLING_US)); - - // Use gesture navigation for consistency. - mNavigationModeSetting.set(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL); - // Keep the device awake during testing. - mStayOnWhilePluggedInSetting.set(BatteryManager.BATTERY_PLUGGED_ANY); - - runWithShellPermissionIdentity(() -> { - final ActivityTaskManager atm = mContext.getSystemService(ActivityTaskManager.class); - atm.removeAllVisibleRecentTasks(); - atm.removeRootTasksWithActivityTypes(new int[] { ACTIVITY_TYPE_STANDARD, - ACTIVITY_TYPE_ASSISTANT, ACTIVITY_TYPE_RECENTS, ACTIVITY_TYPE_UNDEFINED }); - }); - PhoneWindow.sendCloseSystemWindows(mContext, "WmPerfTests"); - - if (Boolean.parseBoolean(arguments.getString(ARGUMENT_KILL_BACKGROUND))) { - runWithShellPermissionIdentity(this::killBackgroundProcesses); - mWaitPreconditionDoneMs = KILL_BACKGROUND_WAIT_MS; - } - // Wait a while for the precondition setup to complete. - SystemClock.sleep(mWaitPreconditionDoneMs); - } - - private void killBackgroundProcesses() { - final ActivityManager am = mContext.getSystemService(ActivityManager.class); - final List<RunningAppProcessInfo> processes = am.getRunningAppProcesses(); - if (processes == null) { - return; - } - for (RunningAppProcessInfo processInfo : processes) { - if (processInfo.importanceReasonCode == RunningAppProcessInfo.REASON_UNKNOWN - && processInfo.importance > RunningAppProcessInfo.IMPORTANCE_SERVICE) { - for (String pkg : processInfo.pkgList) { - am.forceStopPackage(pkg); - } - } - } - } - - /** It only executes once after all tests. */ - @Override - public void testRunFinished(Result result) { - mNavigationModeSetting.close(); - mStayOnWhilePluggedInSetting.close(); - } +public class WmPerfRunListener extends WindowPerfRunPreconditionBase { } diff --git a/apex/appsearch/OWNERS b/apex/appsearch/OWNERS new file mode 100644 index 000000000000..ce0c212a9fe7 --- /dev/null +++ b/apex/appsearch/OWNERS @@ -0,0 +1 @@ +sudheersai@google.com diff --git a/apex/jobscheduler/OWNERS b/apex/jobscheduler/OWNERS index d004eed2a0db..0fe6cdffa5f6 100644 --- a/apex/jobscheduler/OWNERS +++ b/apex/jobscheduler/OWNERS @@ -1,6 +1,6 @@ yamasani@google.com omakoto@google.com -ctate@android.com +ctate@google.com ctate@google.com kwekua@google.com suprabh@google.com
\ No newline at end of file diff --git a/apex/jobscheduler/framework/java/android/app/job/OWNERS b/apex/jobscheduler/framework/java/android/app/job/OWNERS new file mode 100644 index 000000000000..b4a45f585157 --- /dev/null +++ b/apex/jobscheduler/framework/java/android/app/job/OWNERS @@ -0,0 +1,7 @@ +# Bug component: 330738 + +yamasani@google.com +omakoto@google.com +ctate@android.com +ctate@google.com +kwekua@google.com diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java index 9ea402c56088..99a9b97907f4 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java @@ -2044,7 +2044,6 @@ public class JobSchedulerService extends com.android.server.SystemService } maybeRunPendingJobsLocked(); - // Don't remove JOB_EXPIRED in case one came along while processing the queue. } } } @@ -2110,6 +2109,15 @@ public class JobSchedulerService extends com.android.server.SystemService * as many as we can. */ private void queueReadyJobsForExecutionLocked() { + // This method will check and capture all ready jobs, so we don't need to keep any messages + // in the queue. + mHandler.removeMessages(MSG_CHECK_JOB_GREEDY); + // MSG_CHECK_JOB is a weaker form of _GREEDY. Since we're checking and queueing all ready + // jobs, we don't need to keep any MSG_CHECK_JOB messages in the queue. + mHandler.removeMessages(MSG_CHECK_JOB); + // This method will capture all expired jobs that are ready, so there's no need to keep + // the _EXPIRED messages in the queue. + mHandler.removeMessages(MSG_JOB_EXPIRED); if (DEBUG) { Slog.d(TAG, "queuing all ready jobs for execution:"); } diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java index 0b0923a67de6..dd1a0e2478dd 100644 --- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java @@ -1770,9 +1770,18 @@ public class AppStandbyController final int userId = getSendingUserId(); if (Intent.ACTION_PACKAGE_ADDED.equals(action) || Intent.ACTION_PACKAGE_CHANGED.equals(action)) { - clearCarrierPrivilegedApps(); - // ACTION_PACKAGE_ADDED is called even for system app downgrades. - evaluateSystemAppException(pkgName, userId); + final String[] cmpList = intent.getStringArrayExtra( + Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST); + // If this is PACKAGE_ADDED (cmpList == null), or if it's a whole-package + // enable/disable event (cmpList is just the package name itself), drop + // our carrier privileged app & system-app caches and let them refresh + if (cmpList == null + || (cmpList.length == 1 && pkgName.equals(cmpList[0]))) { + clearCarrierPrivilegedApps(); + evaluateSystemAppException(pkgName, userId); + } + // component-level enable/disable can affect bucketing, so we always + // reevaluate that for any PACKAGE_CHANGED mHandler.obtainMessage(MSG_CHECK_PACKAGE_IDLE_STATE, userId, -1, pkgName) .sendToTarget(); } diff --git a/apex/permission/apex_manifest.json b/apex/permission/apex_manifest.json index 7960598affa3..6350d54d695e 100644 --- a/apex/permission/apex_manifest.json +++ b/apex/permission/apex_manifest.json @@ -1,4 +1,4 @@ { "name": "com.android.permission", - "version": 300000000 + "version": 309999999 } diff --git a/apex/statsd/.clang-format b/apex/statsd/.clang-format deleted file mode 100644 index cead3a079435..000000000000 --- a/apex/statsd/.clang-format +++ /dev/null @@ -1,17 +0,0 @@ -BasedOnStyle: Google -AllowShortIfStatementsOnASingleLine: true -AllowShortFunctionsOnASingleLine: false -AllowShortLoopsOnASingleLine: true -BinPackArguments: true -BinPackParameters: true -ColumnLimit: 100 -CommentPragmas: NOLINT:.* -ContinuationIndentWidth: 8 -DerivePointerAlignment: false -IndentWidth: 4 -PointerAlignment: Left -TabWidth: 4 -AccessModifierOffset: -4 -IncludeCategories: - - Regex: '^"Log\.h"' - Priority: -1 diff --git a/apex/statsd/Android.bp b/apex/statsd/Android.bp deleted file mode 100644 index f13861e7ee85..000000000000 --- a/apex/statsd/Android.bp +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -apex { - name: "com.android.os.statsd", - defaults: ["com.android.os.statsd-defaults"], - manifest: "apex_manifest.json", -} - -apex_defaults { - jni_libs: [ - "libstats_jni", - ], - native_shared_libs: [ - "libstatspull", - "libstatssocket", - ], - binaries: ["statsd"], - java_libs: [ - "framework-statsd", - "service-statsd", - ], - compile_multilib: "both", - prebuilts: ["com.android.os.statsd.init.rc"], - name: "com.android.os.statsd-defaults", - updatable: true, - min_sdk_version: "30", - key: "com.android.os.statsd.key", - certificate: ":com.android.os.statsd.certificate", -} - -apex_key { - name: "com.android.os.statsd.key", - public_key: "com.android.os.statsd.avbpubkey", - private_key: "com.android.os.statsd.pem", -} - -android_app_certificate { - name: "com.android.os.statsd.certificate", - // This will use com.android.os.statsd.x509.pem (the cert) and - // com.android.os.statsd.pk8 (the private key) - certificate: "com.android.os.statsd", -} - -prebuilt_etc { - name: "com.android.os.statsd.init.rc", - src: "statsd.rc", - filename: "init.rc", - installable: false, -} - -// JNI library for StatsLog.write -cc_library_shared { - name: "libstats_jni", - srcs: ["jni/**/*.cpp"], - header_libs: ["libnativehelper_header_only"], - shared_libs: [ - "liblog", // Has a stable abi - should not be copied into apex. - "libstatssocket", - ], - stl: "libc++_static", - cflags: [ - "-Wall", - "-Werror", - "-Wextra", - "-Wno-unused-parameter", - ], - apex_available: [ - "com.android.os.statsd", - "test_com.android.os.statsd", - ], -} diff --git a/apex/statsd/OWNERS b/apex/statsd/OWNERS deleted file mode 100644 index bed9600bc955..000000000000 --- a/apex/statsd/OWNERS +++ /dev/null @@ -1,9 +0,0 @@ -jeffreyhuang@google.com -joeo@google.com -jtnguyen@google.com -muhammadq@google.com -ruchirr@google.com -singhtejinder@google.com -tsaichristine@google.com -yaochen@google.com -yro@google.com
\ No newline at end of file diff --git a/apex/statsd/TEST_MAPPING b/apex/statsd/TEST_MAPPING deleted file mode 100644 index 331fe77c708d..000000000000 --- a/apex/statsd/TEST_MAPPING +++ /dev/null @@ -1,19 +0,0 @@ -{ - "presubmit" : [ - { - "name" : "FrameworkStatsdTest" - }, - { - "name" : "LibStatsPullTests" - } - ], - - "postsubmit" : [ - { - "name" : "CtsStatsdHostTestCases" - }, - { - "name" : "GtsStatsdHostTestCases" - } - ] -} diff --git a/apex/statsd/aidl/Android.bp b/apex/statsd/aidl/Android.bp deleted file mode 100644 index f66cf7c9e23c..000000000000 --- a/apex/statsd/aidl/Android.bp +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -filegroup { - name: "framework-statsd-aidl-sources", - srcs: ["**/*.aidl"], -} - -aidl_interface { - name: "statsd-aidl", - unstable: true, - srcs: [ - "android/os/IPendingIntentRef.aidl", - "android/os/IPullAtomCallback.aidl", - "android/os/IPullAtomResultReceiver.aidl", - "android/os/IStatsCompanionService.aidl", - "android/os/IStatsd.aidl", - "android/os/StatsDimensionsValueParcel.aidl", - "android/util/StatsEventParcel.aidl", - ], - host_supported: true, - backend: { - java: { - enabled: false, // framework-statsd and service-statsd use framework-statsd-aidl-sources - }, - cpp: { - enabled: false, - }, - ndk: { - enabled: true, - apex_available: [ - // TODO(b/145923087): Remove this once statsd binary is in apex - "//apex_available:platform", - - "com.android.os.statsd", - "test_com.android.os.statsd", - ], - }, - } -} diff --git a/apex/statsd/aidl/android/os/IPendingIntentRef.aidl b/apex/statsd/aidl/android/os/IPendingIntentRef.aidl deleted file mode 100644 index 000a69992a49..000000000000 --- a/apex/statsd/aidl/android/os/IPendingIntentRef.aidl +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.os; - -import android.os.StatsDimensionsValueParcel; - -/** - * Binder interface to hold a PendingIntent for StatsCompanionService. - * {@hide} - */ -interface IPendingIntentRef { - - /** - * Sends a broadcast to the specified PendingIntent that it should getData now. - * This should be only called from StatsCompanionService. - */ - oneway void sendDataBroadcast(long lastReportTimeNs); - - /** - * Send a broadcast to the specified PendingIntent notifying it that the list of active configs - * has changed. This should be only called from StatsCompanionService. - */ - oneway void sendActiveConfigsChangedBroadcast(in long[] configIds); - - /** - * Send a broadcast to the specified PendingIntent, along with the other information - * specified. This should only be called from StatsCompanionService. - */ - oneway void sendSubscriberBroadcast(long configUid, long configId, long subscriptionId, - long subscriptionRuleId, in String[] cookies, - in StatsDimensionsValueParcel dimensionsValueParcel); -} diff --git a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl deleted file mode 100644 index d56a4bd0a8e5..000000000000 --- a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.os; - -/** - * Binder interface to communicate with the Java-based statistics service helper. - * {@hide} - */ -interface IStatsCompanionService { - /** - * Tell statscompanion that stastd is up and running. - */ - oneway void statsdReady(); - - /** - * Register a repeating alarm for pulling to fire at the given timestamp and every - * intervalMs thereafter (in ms since epoch). - * If polling alarm had already been registered, it will be replaced by new one. - * Uses AlarmManager.setRepeating API, so if the timestamp is in past, alarm fires immediately, - * and alarm is inexact. - */ - oneway void setPullingAlarm(long nextPullTimeMs); - - /** Cancel any repeating pulling alarm. */ - oneway void cancelPullingAlarm(); - - /** - * Register an alarm when we want to trigger subscribers at the given - * timestamp (in ms since epoch). - * If an alarm had already been registered, it will be replaced by new one. - */ - oneway void setAlarmForSubscriberTriggering(long timestampMs); - - /** Cancel any alarm for the purpose of subscriber triggering. */ - oneway void cancelAlarmForSubscriberTriggering(); - - /** - * Ask StatsCompanionService if the given permission is allowed for a particular process - * and user ID. statsd is incapable of doing this check itself because checkCallingPermission - * is not currently supported by libbinder_ndk. - */ - boolean checkPermission(String permission, int pid, int uid); -} diff --git a/apex/statsd/aidl/android/os/IStatsManagerService.aidl b/apex/statsd/aidl/android/os/IStatsManagerService.aidl deleted file mode 100644 index b59a97e25bd0..000000000000 --- a/apex/statsd/aidl/android/os/IStatsManagerService.aidl +++ /dev/null @@ -1,136 +0,0 @@ -/** - * Copyright (c) 2019, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.os; - -import android.app.PendingIntent; -import android.os.IPullAtomCallback; - -/** - * Binder interface to communicate with the Java-based statistics service helper. - * Contains parcelable objects available only in Java. - * {@hide} - */ -interface IStatsManagerService { - - /** - * Registers the given pending intent for this config key. This intent is invoked when the - * memory consumed by the metrics for this configuration approach the pre-defined limits. There - * can be at most one listener per config key. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - void setDataFetchOperation(long configId, in PendingIntent pendingIntent, - in String packageName); - - /** - * Removes the data fetch operation for the specified configuration. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - void removeDataFetchOperation(long configId, in String packageName); - - /** - * Registers the given pending intent for this packagename. This intent is invoked when the - * active status of any of the configs sent by this package changes and will contain a list of - * config ids that are currently active. It also returns the list of configs that are currently - * active. There can be at most one active configs changed listener per package. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - long[] setActiveConfigsChangedOperation(in PendingIntent pendingIntent, in String packageName); - - /** - * Removes the active configs changed operation for the specified package name. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - void removeActiveConfigsChangedOperation(in String packageName); - - /** - * Set the PendingIntent to be used when broadcasting subscriber - * information to the given subscriberId within the given config. - * - * Suppose that the calling uid has added a config with key configKey, and that in this config - * it is specified that when a particular anomaly is detected, a broadcast should be sent to - * a BroadcastSubscriber with id subscriberId. This function links the given pendingIntent with - * that subscriberId (for that config), so that this pendingIntent is used to send the broadcast - * when the anomaly is detected. - * - * This function can only be called by the owner (uid) of the config. It must be called each - * time statsd starts. Later calls overwrite previous calls; only one PendingIntent is stored. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - void setBroadcastSubscriber(long configKey, long subscriberId, in PendingIntent pendingIntent, - in String packageName); - - /** - * Undoes setBroadcastSubscriber() for the (configKey, subscriberId) pair. - * Any broadcasts associated with subscriberId will henceforth not be sent. - * No-op if this (configKey, subscriberId) pair was not associated with an PendingIntent. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - void unsetBroadcastSubscriber(long configKey, long subscriberId, in String packageName); - - /** - * Returns the most recently registered experiment IDs. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - long[] getRegisteredExperimentIds(); - - /** - * Fetches metadata across statsd. Returns byte array representing wire-encoded proto. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - byte[] getMetadata(in String packageName); - - /** - * Fetches data for the specified configuration key. Returns a byte array representing proto - * wire-encoded of ConfigMetricsReportList. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - byte[] getData(in long key, in String packageName); - - /** - * Sets a configuration with the specified config id and subscribes to updates for this - * configuration id. Broadcasts will be sent if this configuration needs to be collected. - * The configuration must be a wire-encoded StatsdConfig. The receiver for this data is - * registered in a separate function. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - void addConfiguration(in long configId, in byte[] config, in String packageName); - - /** - * Removes the configuration with the matching config id. No-op if this config id does not - * exist. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - void removeConfiguration(in long configId, in String packageName); - - /** Tell StatsManagerService to register a puller for the given atom tag with statsd. */ - oneway void registerPullAtomCallback(int atomTag, long coolDownMillis, long timeoutMillis, - in int[] additiveFields, IPullAtomCallback pullerCallback); - - /** Tell StatsManagerService to unregister the pulller for the given atom tag from statsd. */ - oneway void unregisterPullAtomCallback(int atomTag); -} diff --git a/apex/statsd/aidl/android/os/IStatsd.aidl b/apex/statsd/aidl/android/os/IStatsd.aidl deleted file mode 100644 index 066412a9f157..000000000000 --- a/apex/statsd/aidl/android/os/IStatsd.aidl +++ /dev/null @@ -1,230 +0,0 @@ -/** - * Copyright (c) 2017, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.os; - -import android.os.IPendingIntentRef; -import android.os.IPullAtomCallback; -import android.os.ParcelFileDescriptor; - -/** - * Binder interface to communicate with the statistics management service. - * {@hide} - */ -interface IStatsd { - /** - * Tell the stats daemon that the android system server is up and running. - */ - oneway void systemRunning(); - - /** - * Tell the stats daemon that the android system has finished booting. - */ - oneway void bootCompleted(); - - /** - * Tell the stats daemon that the StatsCompanionService is up and running. - * Two-way binder call so that caller knows message received. - */ - void statsCompanionReady(); - - /** - * Tells statsd that it is time to poll some stats. Statsd will be responsible for determing - * what stats to poll and initiating the polling. - * Two-way binder call so that caller's method (and corresponding wakelocks) will linger. - */ - void informPollAlarmFired(); - - /** - * Tells statsd that it is time to handle periodic alarms. Statsd will be responsible for - * determing what alarm subscriber to trigger. - * Two-way binder call so that caller's method (and corresponding wakelocks) will linger. - */ - void informAlarmForSubscriberTriggeringFired(); - - /** - * Tells statsd that the device is about to shutdown. - */ - void informDeviceShutdown(); - - /** - * Inform statsd about a file descriptor for a pipe through which we will pipe version - * and package information for each uid. - * Versions and package information are supplied via UidData proto where info for each app - * is captured in its own element of a repeated ApplicationInfo message. - */ - oneway void informAllUidData(in ParcelFileDescriptor fd); - - /** - * Inform statsd what the uid, version, version_string, and installer are for one app that was - * updated. - */ - oneway void informOnePackage(in String app, in int uid, in long version, - in String version_string, in String installer); - - /** - * Inform stats that an app was removed. - */ - oneway void informOnePackageRemoved(in String app, in int uid); - - /** - * Fetches data for the specified configuration key. Returns a byte array representing proto - * wire-encoded of ConfigMetricsReportList. - * - * Requires Manifest.permission.DUMP. - */ - byte[] getData(in long key, int callingUid); - - /** - * Fetches metadata across statsd. Returns byte array representing wire-encoded proto. - * - * Requires Manifest.permission.DUMP. - */ - byte[] getMetadata(); - - /** - * Sets a configuration with the specified config id and subscribes to updates for this - * configuration key. Broadcasts will be sent if this configuration needs to be collected. - * The configuration must be a wire-encoded StatsdConfig. The receiver for this data is - * registered in a separate function. - * - * Requires Manifest.permission.DUMP. - */ - void addConfiguration(in long configId, in byte[] config, in int callingUid); - - /** - * Registers the given pending intent for this config key. This intent is invoked when the - * memory consumed by the metrics for this configuration approach the pre-defined limits. There - * can be at most one listener per config key. - * - * Requires Manifest.permission.DUMP. - */ - void setDataFetchOperation(long configId, in IPendingIntentRef pendingIntentRef, - int callingUid); - - /** - * Removes the data fetch operation for the specified configuration. - * - * Requires Manifest.permission.DUMP. - */ - void removeDataFetchOperation(long configId, int callingUid); - - /** - * Registers the given pending intent for this packagename. This intent is invoked when the - * active status of any of the configs sent by this package changes and will contain a list of - * config ids that are currently active. It also returns the list of configs that are currently - * active. There can be at most one active configs changed listener per package. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - long[] setActiveConfigsChangedOperation(in IPendingIntentRef pendingIntentRef, int callingUid); - - /** - * Removes the active configs changed operation for the specified package name. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - void removeActiveConfigsChangedOperation(int callingUid); - - /** - * Removes the configuration with the matching config id. No-op if this config id does not - * exist. - * - * Requires Manifest.permission.DUMP. - */ - void removeConfiguration(in long configId, in int callingUid); - - /** - * Set the PendingIntentRef to be used when broadcasting subscriber - * information to the given subscriberId within the given config. - * - * Suppose that the calling uid has added a config with key configId, and that in this config - * it is specified that when a particular anomaly is detected, a broadcast should be sent to - * a BroadcastSubscriber with id subscriberId. This function links the given pendingIntent with - * that subscriberId (for that config), so that this pendingIntent is used to send the broadcast - * when the anomaly is detected. - * - * This function can only be called by the owner (uid) of the config. It must be called each - * time statsd starts. Later calls overwrite previous calls; only one pendingIntent is stored. - * - * Requires Manifest.permission.DUMP. - */ - void setBroadcastSubscriber(long configId, long subscriberId, in IPendingIntentRef pir, - int callingUid); - - /** - * Undoes setBroadcastSubscriber() for the (configId, subscriberId) pair. - * Any broadcasts associated with subscriberId will henceforth not be sent. - * No-op if this (configKey, subscriberId) pair was not associated with an PendingIntentRef. - * - * Requires Manifest.permission.DUMP. - */ - void unsetBroadcastSubscriber(long configId, long subscriberId, int callingUid); - - /** - * Tell the stats daemon that all the pullers registered during boot have been sent. - */ - oneway void allPullersFromBootRegistered(); - - /** - * Registers a puller callback function that, when invoked, pulls the data - * for the specified atom tag. - */ - oneway void registerPullAtomCallback(int uid, int atomTag, long coolDownMillis, - long timeoutMillis,in int[] additiveFields, - IPullAtomCallback pullerCallback); - - /** - * Registers a puller callback function that, when invoked, pulls the data - * for the specified atom tag. - * - * Enforces the REGISTER_STATS_PULL_ATOM permission. - */ - oneway void registerNativePullAtomCallback(int atomTag, long coolDownMillis, long timeoutMillis, - in int[] additiveFields, IPullAtomCallback pullerCallback); - - /** - * Unregisters any pullAtomCallback for the given uid/atom. - */ - oneway void unregisterPullAtomCallback(int uid, int atomTag); - - /** - * Unregisters any pullAtomCallback for the given atom + caller. - * - * Enforces the REGISTER_STATS_PULL_ATOM permission. - */ - oneway void unregisterNativePullAtomCallback(int atomTag); - - /** - * The install requires staging. - */ - const int FLAG_REQUIRE_STAGING = 0x01; - - /** - * Rollback is enabled with this install. - */ - const int FLAG_ROLLBACK_ENABLED = 0x02; - - /** - * Requires low latency monitoring. - */ - const int FLAG_REQUIRE_LOW_LATENCY_MONITOR = 0x04; - - /** - * Returns the most recently registered experiment IDs. - */ - long[] getRegisteredExperimentIds(); -} diff --git a/apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl b/apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl deleted file mode 100644 index 05f78d00348e..000000000000 --- a/apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl +++ /dev/null @@ -1,21 +0,0 @@ -package android.os; - -/** - * @hide - */ -parcelable StatsDimensionsValueParcel { - // Field equals atomTag for top level StatsDimensionsValueParcels or - // positions in depth (1-indexed) for lower level parcels. - int field; - - // Indicator for which type of value is stored. Should be set to one - // of the constants in StatsDimensionsValue.java. - int valueType; - - String stringValue; - int intValue; - long longValue; - boolean boolValue; - float floatValue; - StatsDimensionsValueParcel[] tupleValue; -} diff --git a/apex/statsd/aidl/android/util/StatsEventParcel.aidl b/apex/statsd/aidl/android/util/StatsEventParcel.aidl deleted file mode 100644 index add8bfb47b1a..000000000000 --- a/apex/statsd/aidl/android/util/StatsEventParcel.aidl +++ /dev/null @@ -1,8 +0,0 @@ -package android.util; - -/** - * @hide - */ -parcelable StatsEventParcel { - byte[] buffer; -} diff --git a/apex/statsd/apex_manifest.json b/apex/statsd/apex_manifest.json deleted file mode 100644 index 1d029c61b4bf..000000000000 --- a/apex/statsd/apex_manifest.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "com.android.os.statsd", - "version": 309999900 -} - diff --git a/apex/statsd/com.android.os.statsd.avbpubkey b/apex/statsd/com.android.os.statsd.avbpubkey Binary files differdeleted file mode 100644 index d78af8b8bef2..000000000000 --- a/apex/statsd/com.android.os.statsd.avbpubkey +++ /dev/null diff --git a/apex/statsd/com.android.os.statsd.pem b/apex/statsd/com.android.os.statsd.pem deleted file mode 100644 index 558e17fd6864..000000000000 --- a/apex/statsd/com.android.os.statsd.pem +++ /dev/null @@ -1,51 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIJKgIBAAKCAgEA893bbpkivKEiNgfknYBSlzC0csaKU/ddBm5Pb4ZFuab+LQSR -9DDc5JrsmxyrsrvuwL/zAtMbkyYWzEiUxJtx/w0bw8rC90GoPRSCmxyI0ZK8FuPy -IAQ7UeNfTWZ485mAUaTSasGIfQ3DY4F0P+aUSijeG3NUY02nALHDMqJX7lXR+mL1 -DUYDg05KB0jxQwlYqBeujTPPiAzEqm3PlBoHuan8/qgK2wdQMTVg/fieUD3lupmV -Wj2dRZgqfBPA16ZbV4Uo0j0bZSf+fQLiXlU2VJGb5i/FQfjLqMKGABDI0MgK7Sc2 -m4ySpV4g4XKDv/vw6Dw4kwWC7mATEVAkH+q6V7uiZeN6a7w30UMtPI8fPaUvAP3L -VBjCBIv/3m+CKkWcNxOZ3sQBQl5bS05dxcfiVsBvBLYbvQgC+Wy0Sc3b+1pXFT/E -uAsbZ4CyVsi1+PAdx3h5e2QAyNCXgZDOcvTUyxY6JLTE0LOVHmI4fJEujBex//Oz -PCRHvC8K+KiljyQWf/NYrLSD3QGYAjVMtQh7yu2yhzWzgBUxyhuv3rY4ATXsN3bJ -wW4w7/L/RSLSW5+lp/NoJOD9utbsKTyGMHOY6K8JLOmhv3ORoAEmLYlFTI+FqBi9 -AH1HQEKCyh8Z/bYHLUzGWl6FqAMtcnuintv40BbKyt0/D1ItdbSNKmOZ5rkCAwEA -AQKCAgAY7ll8mRNADYkd1Pi+UVwgMM6B3WJO6z8LZUOhtyxxqmzZ1VnGiShMBrqh -sPCsuSHTeswxQbvT81TpVZI/91RUKtbn0VbVSFUWyX4AtY4XPtUT0gHy2/vkh0Y6 -93ruDIdd0Wfhmh+GCV4sUhO8ZKpMWpk6XTQHYuzr2UCHcKlkqElrO6qpzLqXNe3D -iOWBYPc7WBB0RxO0aPnCIq/SCEc55/MBZdSWR80e+sILtNsagPl3djQaoanub3wI -a0yPv2YfMHHX7H9cfBY8WYsi8bs4MhqqEcAs2m6XtitU3mJpVcooLJYcmOZ1GYZr -BfYKLouWcnGmNi4IiLHqVzMaQDkEhAZsRaAXCkoVVrFBedLlmLPpiUIQlINF4vxe -3IcekTKWyMzkU6h+K8T15MU5mLSqeL2Gji1JIwKJno51FZ9uc++pUJVtfYQmNny8 -8RKvQ1hv/S5yLQKgN+VkNbaWlUoMP73dtUe3m/At71/2Dj7xB0KtcgT1lEMrM1GR -oynJAJLz/d0n5RUUREwkZZMcA4fQVC7Db6vpK69jPiQMShpZ3JKCEjfYLUuN0slt -FPhjiR175E0vTRuLoIj4kXNwLLswH0c9zqrKM2S92SCxAV3E4JJGKhUZalvT9s1g -LrPhMCl6CsOES98T87d3RyAIK0iVRCnRUG3bc+8rzyRd4fzkAQKCAQEA/UjmCSm3 -H46t/1w7YBZPew7SFQOAJe81iDzbonc3fNPD2R8lxtD3MwdvrQ5f9fhT4+uveWNr -dyBX7ppnissyM3LZRN+7BdeIVVeIPVen6Ou9W2i7q18ZoQx9IpRcZEw5tGJFZaGx -EmyPN4i1K0ccUkGbBvbXXQ/tcG3wElRpBAc5/TQ8vrpUgHll2/MbYhowx6P9uHv5 -thoyG98X+7Fbg8ikzw5GtyuedXfyX1CpJ7yUQVS2PEaOMXOkZdx2bbWRAYYCpsqB -dMmjs2PsFhZHu6CpLhlocHbfUiRztCUCaMZJPQXFSVmy8QDMvZEdVLvad9Poi8ny -lmHVRgxaNbAtIQKCAQEA9nscqRaaO7hIX9bOUxcDbI0486Ws4H0hAFApIN+6/LP4 -hkxey3xWArTYWrvSG1d5GkJAdn99ayWzo2PevmJlrhIJiO1QqYBAk+87cnhwSCmB -kb0sGkNWcc/xNRy7eqdhyCmVhaUnIbORee+cD6qiu/l2BAclTf2ZARFOGXjhQkvt -cDbc/9ZR467ceXbiTIU34Be4xnNAY1mo59jvwl9eqxgpefYTqPhcZ7OmlDli77Hd -XuRfuxLZCscv7A9M5Enc2zwOEP5VwRNwYzYtMm2Yh9CQZxNWC7JVh1Gw5MPFzsGl -sgEdb4WGneN6PPLQHK7NF0f7wYSNnF0i3XSME9MumQKCAQEA0qMbWydr+TyJC0LC -xigHtUkgAQXGPsXuePxTk4sdhBwAVcKHgg4qZi+a+gpoV4BLE9LfPU4nAwzM08to -rI5Lk2nBsnt1Z2hVItQGoy0QoK3b7fbti5ktETf3oRhMtcSGgLLxD5ImVjId8Isq -T3F15hpVOLdzZxtl1Qg4jKXSJ91yplYY5mzC9Yz/3qkQbsdlJcIFsLS5eG3UmkUw -Bsr6VmA4X1F6Eb6eqwYzdHz6D+fOS36NhxcODaYkY+myO46xptixv8/NVTiTgQ5q -OfwRb8Iur/3FUzIoioFyD7Bvjn7ITY1NArEsFS0bF9Nk1yDakKiUThyGN/Xojbac -FuYKwQKCAQEAxOWJ+qU8phJLdowBHC0ZJiEWasRhep9auoZOpJ01IWOfV6EwZLs5 -dkYDQ1Agwoi5DDn6hu7HQM3IV/CS4mF2OnzcMw7ozc7PR53nTkVZ5LuLbuHAlmZO -avKjDDucpJmLqjtV34IT5X8t6kt3zqgQAbuBBCy1Jz07ebfaPMzsnWpMDcU1/AW4 -OvrX0wweMOSGwzQP/i/ZMsRQAo2w0gQfeuv9Thk+kU99ebXwjx3co//hCEnFE4s1 -6L8/0AJU+VTr4hJyZi7WUDt4HzkLF+qm22/Hux+eMA/Q9R1UAxtFLCpTdAQiAJGY -/Q3X+1I434DgAwYU3f1Gpq9cB65vq/KamQKCAQEAjIub5wde/ttHlLALvnOXrbqe -nUIfWHExMzhul/rkr8fFEJwij2nZUuN2EWUGzBWQQoNXw5QKHLZyPsyFUOa/P2BS -osnffAa+sumL4k36E71xFdTVV5ExyTXZVB49sPmUpivP9gEucFFqDHKjGsF45dBF -+DZdykLUIv+/jQUzXGkZ5Wv/r52YUNho4EZdwnlJ2so7cxnsYnjW+c1nlp17tkq5 -DfwktkeD9iFzlaZ66vLoO44luaBm+lC3xM2sHinOTwbk0gvhJAIoLfkOYhpmGc8A -4W/E1OHfVz6xqVDsMBFhRbQpHNkf8XZNqkIoqHVMTaMOJJlM+lb0+A9B8Bm/XA== ------END RSA PRIVATE KEY----- diff --git a/apex/statsd/com.android.os.statsd.pk8 b/apex/statsd/com.android.os.statsd.pk8 Binary files differdeleted file mode 100644 index 49910f80a05c..000000000000 --- a/apex/statsd/com.android.os.statsd.pk8 +++ /dev/null diff --git a/apex/statsd/com.android.os.statsd.x509.pem b/apex/statsd/com.android.os.statsd.x509.pem deleted file mode 100644 index e7b16b2048cb..000000000000 --- a/apex/statsd/com.android.os.statsd.x509.pem +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFDTCCAvWgAwIBAgIUCnta1LAl5fMMLLQx//4zWz9A2A8wDQYJKoZIhvcNAQEL -BQAwFTETMBEGA1UECgwKR29vZ2xlIExMQzAgFw0xOTA4MTIyMjM5MzBaGA80NzU3 -MDcwODIyMzkzMFowFTETMBEGA1UECgwKR29vZ2xlIExMQzCCAiIwDQYJKoZIhvcN -AQEBBQADggIPADCCAgoCggIBAOranWZ19jkXCF9WIlXv01tUUvLKMHWKV7X9Earw -cL7/aax0pFbNJutgyBUiOszbR+0T7quZxz6jACu+6y7iaMJnvMluZsfTi+p2UvQt -y6Ql7ZUOQ7bVluCFIW5hZ+8d9RrLmZdvX1r4YfF6HufDBkAbj+os+y6407OezJAV -8EATpemc9gsCC4RJZpwzTs1RUXMD4UoNrLZAE8+7iaJZeBxmz0MAPj92pYc9M7/d -xInzYvOR08/uEpHt8jlMdVgSQS/FaRlIOIqcGBk3cjkjDlpVATQ4Hyjy+IPQPjTD -bJUmDJiYeBCyY/pYZQvTQjl8s+fvykTsF9Lfb+E+PhZ0+N8pRi7sUSpisZHSiqaN -W3oxYWc0YQSuzygHHog8HH/azHX5L805g/+Rwfb/cUF9eJgjq0vrkFnsz4UKgKNV -hHL90mfqpbc2UvJ8VY8BvIjbsHQ77LrBKlqI9VMPorttpTOuwHHJPKsyN972F0Ul -lRB6CwFE8csVGWXoNaDZWBv7xTDdbdirmlKDNueg9pw6ksYV2Is9Dv8PxmsZvb+4 -oftC/hb4X1Pudn01PPs9Tx44CwHuVLENUwlDEVzG5zNetsv9kAuCYt3VRVF+NYqj -NAfLbxCKLe25wGzJrZUEJ1YrYIjpUbfwnttEad/9Pu13DAS7HZwn5vwqEKB/1LlT -NSUXAgMBAAGjUzBRMB0GA1UdDgQWBBSKElkhJSbzgh8+iysye8SrkmJ62DAfBgNV -HSMEGDAWgBSKElkhJSbzgh8+iysye8SrkmJ62DAPBgNVHRMBAf8EBTADAQH/MA0G -CSqGSIb3DQEBCwUAA4ICAQANFGnc2wJBrFbh2nzhl06g4TjPKGRCw365vZ1A3T9O -jXP0lToHDxB33TpKk6d7zszR1uPphQQxgzhSVZB/jx8q4kWSSoKoF9Dlx7h8rAt+ -2TM5DaBvxrwu5mqOALwQuF81wap1Pl2L2fFHvygCm8b+Ci4iS5vcr0axNnp1rK1b -vUtRWY4mfxTjJYcgeCVUGskqTb+cCxQZ6Icno6VTKajT1FybRmD3KZJaUuLbNEN+ -IE4nGTMG2WZ5Hl2vR8JJp1sYYn8T3ElMAb0MSNFkqsfI+tToEwGsuJDgYEdtEnzf -lTycQvn5NhrIZRRN3pqSyWpAU7p9mmyTK0PHMz2D/Rtfb7lE692vXzxCmZND51mc -YXCCoanV6eZZ7Sbqzh60+5QV38hgFBst5l8CcFaWWSFK9nBWdzS5lhs9lmQ4aiYd -IE0qsNZgMob+TTP1VW39hu4EDjNmOrKfimM9J2tcPZ5QP01DgETPvAsB7vn2Xz9J -HGt5ntiSV4W2izDP8viQ1M5NvfdBaUhcnNsE6/sxfU0USRs2hrEp1oiqrv4p6V0P -qOt7C2/YtJzkrxfsHZAxBUSRHa7LwtzgeiJDUivHn94VnAzSAH8MLx6CzDPQ8HWN -NiZFxTKfMVyjEmbQ2PalHWB8pWtpdEh7X4rzaqhnLBTis3pGssASgo3ArLIYleAU -+g== ------END CERTIFICATE----- diff --git a/apex/statsd/framework/Android.bp b/apex/statsd/framework/Android.bp deleted file mode 100644 index e4299f52ff7d..000000000000 --- a/apex/statsd/framework/Android.bp +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package { - default_visibility: [ ":__pkg__" ] -} - -genrule { - name: "statslog-statsd-java-gen", - tools: ["stats-log-api-gen"], - cmd: "$(location stats-log-api-gen) --java $(out) --module statsd" + - " --javaPackage com.android.internal.statsd --javaClass StatsdStatsLog", - out: ["com/android/internal/statsd/StatsdStatsLog.java"], -} - -java_library_static { - name: "statslog-statsd", - srcs: [ - ":statslog-statsd-java-gen", - ], - visibility: [ - "//cts/hostsidetests/statsd/apps:__subpackages__", - "//vendor:__subpackages__", - ], -} - -filegroup { - name: "framework-statsd-sources", - srcs: [ - "java/**/*.java", - ":framework-statsd-aidl-sources", - ":statslog-statsd-java-gen", - ], - visibility: [ - "//frameworks/base", // For the "global" stubs. - "//frameworks/base/apex/statsd:__subpackages__", - "//packages/modules/StatsD/apex:__subpackages__", - ], -} -java_sdk_library { - name: "framework-statsd", - defaults: ["framework-module-defaults"], - installable: true, - - srcs: [ - ":framework-statsd-sources", - ], - - permitted_packages: [ - "android.app", - "android.os", - "android.util", - // From :statslog-statsd-java-gen - "com.android.internal.statsd", - ], - - api_packages: [ - "android.app", - "android.os", - "android.util", - ], - - hostdex: true, // for hiddenapi check - - impl_library_visibility: [ - "//frameworks/base/apex/statsd/framework/test:__subpackages__", - "//packages/modules/StatsD/apex/framework/test:__subpackages__", - ], - - apex_available: [ - "com.android.os.statsd", - "test_com.android.os.statsd", - ], -} diff --git a/apex/statsd/framework/api/current.txt b/apex/statsd/framework/api/current.txt deleted file mode 100644 index a65569347e7d..000000000000 --- a/apex/statsd/framework/api/current.txt +++ /dev/null @@ -1,12 +0,0 @@ -// Signature format: 2.0 -package android.util { - - public final class StatsLog { - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public static boolean logBinaryPushStateChanged(@NonNull String, long, int, int, @NonNull long[]); - method public static boolean logEvent(int); - method public static boolean logStart(int); - method public static boolean logStop(int); - } - -} - diff --git a/apex/statsd/framework/api/module-lib-current.txt b/apex/statsd/framework/api/module-lib-current.txt deleted file mode 100644 index 8b6e2170002e..000000000000 --- a/apex/statsd/framework/api/module-lib-current.txt +++ /dev/null @@ -1,10 +0,0 @@ -// Signature format: 2.0 -package android.os { - - public class StatsFrameworkInitializer { - method public static void registerServiceWrappers(); - method public static void setStatsServiceManager(@NonNull android.os.StatsServiceManager); - } - -} - diff --git a/apex/statsd/framework/api/module-lib-removed.txt b/apex/statsd/framework/api/module-lib-removed.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/apex/statsd/framework/api/module-lib-removed.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/apex/statsd/framework/api/removed.txt b/apex/statsd/framework/api/removed.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/apex/statsd/framework/api/removed.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/apex/statsd/framework/api/system-current.txt b/apex/statsd/framework/api/system-current.txt deleted file mode 100644 index 3ea572450c1c..000000000000 --- a/apex/statsd/framework/api/system-current.txt +++ /dev/null @@ -1,111 +0,0 @@ -// Signature format: 2.0 -package android.app { - - public final class StatsManager { - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void addConfig(long, byte[]) throws android.app.StatsManager.StatsUnavailableException; - method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean addConfiguration(long, byte[]); - method @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM) public void clearPullAtomCallback(int); - method @Deprecated @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getData(long); - method @Deprecated @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getMetadata(); - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long[] getRegisteredExperimentIds() throws android.app.StatsManager.StatsUnavailableException; - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getReports(long) throws android.app.StatsManager.StatsUnavailableException; - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getStatsMetadata() throws android.app.StatsManager.StatsUnavailableException; - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void removeConfig(long) throws android.app.StatsManager.StatsUnavailableException; - method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean removeConfiguration(long); - method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long[] setActiveConfigsChangedOperation(@Nullable android.app.PendingIntent) throws android.app.StatsManager.StatsUnavailableException; - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void setBroadcastSubscriber(android.app.PendingIntent, long, long) throws android.app.StatsManager.StatsUnavailableException; - method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setBroadcastSubscriber(long, long, android.app.PendingIntent); - method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setDataFetchOperation(long, android.app.PendingIntent); - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void setFetchReportsOperation(android.app.PendingIntent, long) throws android.app.StatsManager.StatsUnavailableException; - method @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM) public void setPullAtomCallback(int, @Nullable android.app.StatsManager.PullAtomMetadata, @NonNull java.util.concurrent.Executor, @NonNull android.app.StatsManager.StatsPullAtomCallback); - field public static final String ACTION_STATSD_STARTED = "android.app.action.STATSD_STARTED"; - field public static final String EXTRA_STATS_ACTIVE_CONFIG_KEYS = "android.app.extra.STATS_ACTIVE_CONFIG_KEYS"; - field public static final String EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES = "android.app.extra.STATS_BROADCAST_SUBSCRIBER_COOKIES"; - field public static final String EXTRA_STATS_CONFIG_KEY = "android.app.extra.STATS_CONFIG_KEY"; - field public static final String EXTRA_STATS_CONFIG_UID = "android.app.extra.STATS_CONFIG_UID"; - field public static final String EXTRA_STATS_DIMENSIONS_VALUE = "android.app.extra.STATS_DIMENSIONS_VALUE"; - field public static final String EXTRA_STATS_SUBSCRIPTION_ID = "android.app.extra.STATS_SUBSCRIPTION_ID"; - field public static final String EXTRA_STATS_SUBSCRIPTION_RULE_ID = "android.app.extra.STATS_SUBSCRIPTION_RULE_ID"; - field public static final int PULL_SKIP = 1; // 0x1 - field public static final int PULL_SUCCESS = 0; // 0x0 - } - - public static class StatsManager.PullAtomMetadata { - method @Nullable public int[] getAdditiveFields(); - method public long getCoolDownMillis(); - method public long getTimeoutMillis(); - } - - public static class StatsManager.PullAtomMetadata.Builder { - ctor public StatsManager.PullAtomMetadata.Builder(); - method @NonNull public android.app.StatsManager.PullAtomMetadata build(); - method @NonNull public android.app.StatsManager.PullAtomMetadata.Builder setAdditiveFields(@NonNull int[]); - method @NonNull public android.app.StatsManager.PullAtomMetadata.Builder setCoolDownMillis(long); - method @NonNull public android.app.StatsManager.PullAtomMetadata.Builder setTimeoutMillis(long); - } - - public static interface StatsManager.StatsPullAtomCallback { - method public int onPullAtom(int, @NonNull java.util.List<android.util.StatsEvent>); - } - - public static class StatsManager.StatsUnavailableException extends android.util.AndroidException { - ctor public StatsManager.StatsUnavailableException(String); - ctor public StatsManager.StatsUnavailableException(String, Throwable); - } - -} - -package android.os { - - public final class StatsDimensionsValue implements android.os.Parcelable { - method public int describeContents(); - method public boolean getBooleanValue(); - method public int getField(); - method public float getFloatValue(); - method public int getIntValue(); - method public long getLongValue(); - method public String getStringValue(); - method public java.util.List<android.os.StatsDimensionsValue> getTupleValueList(); - method public int getValueType(); - method public boolean isValueType(int); - method public void writeToParcel(android.os.Parcel, int); - field public static final int BOOLEAN_VALUE_TYPE = 5; // 0x5 - field @NonNull public static final android.os.Parcelable.Creator<android.os.StatsDimensionsValue> CREATOR; - field public static final int FLOAT_VALUE_TYPE = 6; // 0x6 - field public static final int INT_VALUE_TYPE = 3; // 0x3 - field public static final int LONG_VALUE_TYPE = 4; // 0x4 - field public static final int STRING_VALUE_TYPE = 2; // 0x2 - field public static final int TUPLE_VALUE_TYPE = 7; // 0x7 - } - -} - -package android.util { - - public final class StatsEvent { - method @NonNull public static android.util.StatsEvent.Builder newBuilder(); - } - - public static final class StatsEvent.Builder { - method @NonNull public android.util.StatsEvent.Builder addBooleanAnnotation(byte, boolean); - method @NonNull public android.util.StatsEvent.Builder addIntAnnotation(byte, int); - method @NonNull public android.util.StatsEvent build(); - method @NonNull public android.util.StatsEvent.Builder setAtomId(int); - method @NonNull public android.util.StatsEvent.Builder usePooledBuffer(); - method @NonNull public android.util.StatsEvent.Builder writeAttributionChain(@NonNull int[], @NonNull String[]); - method @NonNull public android.util.StatsEvent.Builder writeBoolean(boolean); - method @NonNull public android.util.StatsEvent.Builder writeByteArray(@NonNull byte[]); - method @NonNull public android.util.StatsEvent.Builder writeFloat(float); - method @NonNull public android.util.StatsEvent.Builder writeInt(int); - method @NonNull public android.util.StatsEvent.Builder writeKeyValuePairs(@Nullable android.util.SparseIntArray, @Nullable android.util.SparseLongArray, @Nullable android.util.SparseArray<java.lang.String>, @Nullable android.util.SparseArray<java.lang.Float>); - method @NonNull public android.util.StatsEvent.Builder writeLong(long); - method @NonNull public android.util.StatsEvent.Builder writeString(@NonNull String); - } - - public final class StatsLog { - method public static void write(@NonNull android.util.StatsEvent); - method public static void writeRaw(@NonNull byte[], int); - } - -} - diff --git a/apex/statsd/framework/api/system-removed.txt b/apex/statsd/framework/api/system-removed.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/apex/statsd/framework/api/system-removed.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/apex/statsd/framework/java/android/app/StatsManager.java b/apex/statsd/framework/java/android/app/StatsManager.java deleted file mode 100644 index 41803cfd6960..000000000000 --- a/apex/statsd/framework/java/android/app/StatsManager.java +++ /dev/null @@ -1,725 +0,0 @@ -/* - * Copyright 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.app; - -import static android.Manifest.permission.DUMP; -import static android.Manifest.permission.PACKAGE_USAGE_STATS; - -import android.annotation.CallbackExecutor; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.RequiresPermission; -import android.annotation.SystemApi; -import android.content.Context; -import android.os.Binder; -import android.os.IPullAtomCallback; -import android.os.IPullAtomResultReceiver; -import android.os.IStatsManagerService; -import android.os.RemoteException; -import android.os.StatsFrameworkInitializer; -import android.util.AndroidException; -import android.util.Log; -import android.util.StatsEvent; -import android.util.StatsEventParcel; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Executor; - -/** - * API for statsd clients to send configurations and retrieve data. - * - * @hide - */ -@SystemApi -public final class StatsManager { - private static final String TAG = "StatsManager"; - private static final boolean DEBUG = false; - - private static final Object sLock = new Object(); - private final Context mContext; - - @GuardedBy("sLock") - private IStatsManagerService mStatsManagerService; - - /** - * Long extra of uid that added the relevant stats config. - */ - public static final String EXTRA_STATS_CONFIG_UID = "android.app.extra.STATS_CONFIG_UID"; - /** - * Long extra of the relevant stats config's configKey. - */ - public static final String EXTRA_STATS_CONFIG_KEY = "android.app.extra.STATS_CONFIG_KEY"; - /** - * Long extra of the relevant statsd_config.proto's Subscription.id. - */ - public static final String EXTRA_STATS_SUBSCRIPTION_ID = - "android.app.extra.STATS_SUBSCRIPTION_ID"; - /** - * Long extra of the relevant statsd_config.proto's Subscription.rule_id. - */ - public static final String EXTRA_STATS_SUBSCRIPTION_RULE_ID = - "android.app.extra.STATS_SUBSCRIPTION_RULE_ID"; - /** - * List<String> of the relevant statsd_config.proto's BroadcastSubscriberDetails.cookie. - * Obtain using {@link android.content.Intent#getStringArrayListExtra(String)}. - */ - public static final String EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES = - "android.app.extra.STATS_BROADCAST_SUBSCRIBER_COOKIES"; - /** - * Extra of a {@link android.os.StatsDimensionsValue} representing sliced dimension value - * information. - */ - public static final String EXTRA_STATS_DIMENSIONS_VALUE = - "android.app.extra.STATS_DIMENSIONS_VALUE"; - /** - * Long array extra of the active configs for the uid that added those configs. - */ - public static final String EXTRA_STATS_ACTIVE_CONFIG_KEYS = - "android.app.extra.STATS_ACTIVE_CONFIG_KEYS"; - - /** - * Broadcast Action: Statsd has started. - * Configurations and PendingIntents can now be sent to it. - */ - public static final String ACTION_STATSD_STARTED = "android.app.action.STATSD_STARTED"; - - // Pull atom callback return codes. - /** - * Value indicating that this pull was successful and that the result should be used. - * - **/ - public static final int PULL_SUCCESS = 0; - - /** - * Value indicating that this pull was unsuccessful and that the result should not be used. - **/ - public static final int PULL_SKIP = 1; - - /** - * @hide - **/ - @VisibleForTesting public static final long DEFAULT_COOL_DOWN_MILLIS = 1_000L; // 1 second. - - /** - * @hide - **/ - @VisibleForTesting public static final long DEFAULT_TIMEOUT_MILLIS = 2_000L; // 2 seconds. - - /** - * Constructor for StatsManagerClient. - * - * @hide - */ - public StatsManager(Context context) { - mContext = context; - } - - /** - * Adds the given configuration and associates it with the given configKey. If a config with the - * given configKey already exists for the caller's uid, it is replaced with the new one. - * - * @param configKey An arbitrary integer that allows clients to track the configuration. - * @param config Wire-encoded StatsdConfig proto that specifies metrics (and all - * dependencies eg, conditions and matchers). - * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service - * @throws IllegalArgumentException if config is not a wire-encoded StatsdConfig proto - */ - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public void addConfig(long configKey, byte[] config) throws StatsUnavailableException { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - // can throw IllegalArgumentException - service.addConfiguration(configKey, config, mContext.getOpPackageName()); - } catch (RemoteException e) { - Log.e(TAG, "Failed to connect to statsmanager when adding configuration"); - throw new StatsUnavailableException("could not connect", e); - } catch (SecurityException e) { - throw new StatsUnavailableException(e.getMessage(), e); - } catch (IllegalStateException e) { - Log.e(TAG, "Failed to addConfig in statsmanager"); - throw new StatsUnavailableException(e.getMessage(), e); - } - } - } - - // TODO: Temporary for backwards compatibility. Remove. - /** - * @deprecated Use {@link #addConfig(long, byte[])} - */ - @Deprecated - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public boolean addConfiguration(long configKey, byte[] config) { - try { - addConfig(configKey, config); - return true; - } catch (StatsUnavailableException | IllegalArgumentException e) { - return false; - } - } - - /** - * Remove a configuration from logging. - * - * @param configKey Configuration key to remove. - * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service - */ - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public void removeConfig(long configKey) throws StatsUnavailableException { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - service.removeConfiguration(configKey, mContext.getOpPackageName()); - } catch (RemoteException e) { - Log.e(TAG, "Failed to connect to statsmanager when removing configuration"); - throw new StatsUnavailableException("could not connect", e); - } catch (SecurityException e) { - throw new StatsUnavailableException(e.getMessage(), e); - } catch (IllegalStateException e) { - Log.e(TAG, "Failed to removeConfig in statsmanager"); - throw new StatsUnavailableException(e.getMessage(), e); - } - } - } - - // TODO: Temporary for backwards compatibility. Remove. - /** - * @deprecated Use {@link #removeConfig(long)} - */ - @Deprecated - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public boolean removeConfiguration(long configKey) { - try { - removeConfig(configKey); - return true; - } catch (StatsUnavailableException e) { - return false; - } - } - - /** - * Set the PendingIntent to be used when broadcasting subscriber information to the given - * subscriberId within the given config. - * <p> - * Suppose that the calling uid has added a config with key configKey, and that in this config - * it is specified that when a particular anomaly is detected, a broadcast should be sent to - * a BroadcastSubscriber with id subscriberId. This function links the given pendingIntent with - * that subscriberId (for that config), so that this pendingIntent is used to send the broadcast - * when the anomaly is detected. - * <p> - * When statsd sends the broadcast, the PendingIntent will used to send an intent with - * information of - * {@link #EXTRA_STATS_CONFIG_UID}, - * {@link #EXTRA_STATS_CONFIG_KEY}, - * {@link #EXTRA_STATS_SUBSCRIPTION_ID}, - * {@link #EXTRA_STATS_SUBSCRIPTION_RULE_ID}, - * {@link #EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES}, and - * {@link #EXTRA_STATS_DIMENSIONS_VALUE}. - * <p> - * This function can only be called by the owner (uid) of the config. It must be called each - * time statsd starts. The config must have been added first (via {@link #addConfig}). - * - * @param pendingIntent the PendingIntent to use when broadcasting info to the subscriber - * associated with the given subscriberId. May be null, in which case - * it undoes any previous setting of this subscriberId. - * @param configKey The integer naming the config to which this subscriber is attached. - * @param subscriberId ID of the subscriber, as used in the config. - * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service - */ - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public void setBroadcastSubscriber( - PendingIntent pendingIntent, long configKey, long subscriberId) - throws StatsUnavailableException { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - if (pendingIntent != null) { - service.setBroadcastSubscriber(configKey, subscriberId, pendingIntent, - mContext.getOpPackageName()); - } else { - service.unsetBroadcastSubscriber(configKey, subscriberId, - mContext.getOpPackageName()); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to connect to statsmanager when adding broadcast subscriber", - e); - throw new StatsUnavailableException("could not connect", e); - } catch (SecurityException e) { - throw new StatsUnavailableException(e.getMessage(), e); - } - } - } - - // TODO: Temporary for backwards compatibility. Remove. - /** - * @deprecated Use {@link #setBroadcastSubscriber(PendingIntent, long, long)} - */ - @Deprecated - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public boolean setBroadcastSubscriber( - long configKey, long subscriberId, PendingIntent pendingIntent) { - try { - setBroadcastSubscriber(pendingIntent, configKey, subscriberId); - return true; - } catch (StatsUnavailableException e) { - return false; - } - } - - /** - * Registers the operation that is called to retrieve the metrics data. This must be called - * each time statsd starts. The config must have been added first (via {@link #addConfig}, - * although addConfig could have been called on a previous boot). This operation allows - * statsd to send metrics data whenever statsd determines that the metrics in memory are - * approaching the memory limits. The fetch operation should call {@link #getReports} to fetch - * the data, which also deletes the retrieved metrics from statsd's memory. - * - * @param pendingIntent the PendingIntent to use when broadcasting info to the subscriber - * associated with the given subscriberId. May be null, in which case - * it removes any associated pending intent with this configKey. - * @param configKey The integer naming the config to which this operation is attached. - * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service - */ - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public void setFetchReportsOperation(PendingIntent pendingIntent, long configKey) - throws StatsUnavailableException { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - if (pendingIntent == null) { - service.removeDataFetchOperation(configKey, mContext.getOpPackageName()); - } else { - service.setDataFetchOperation(configKey, pendingIntent, - mContext.getOpPackageName()); - } - - } catch (RemoteException e) { - Log.e(TAG, "Failed to connect to statsmanager when registering data listener."); - throw new StatsUnavailableException("could not connect", e); - } catch (SecurityException e) { - throw new StatsUnavailableException(e.getMessage(), e); - } - } - } - - /** - * Registers the operation that is called whenever there is a change in which configs are - * active. This must be called each time statsd starts. This operation allows - * statsd to inform clients that they should pull data of the configs that are currently - * active. The activeConfigsChangedOperation should set periodic alarms to pull data of configs - * that are active and stop pulling data of configs that are no longer active. - * - * @param pendingIntent the PendingIntent to use when broadcasting info to the subscriber - * associated with the given subscriberId. May be null, in which case - * it removes any associated pending intent for this client. - * @return A list of configs that are currently active for this client. If the pendingIntent is - * null, this will be an empty list. - * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service - */ - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public @NonNull long[] setActiveConfigsChangedOperation(@Nullable PendingIntent pendingIntent) - throws StatsUnavailableException { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - if (pendingIntent == null) { - service.removeActiveConfigsChangedOperation(mContext.getOpPackageName()); - return new long[0]; - } else { - return service.setActiveConfigsChangedOperation(pendingIntent, - mContext.getOpPackageName()); - } - - } catch (RemoteException e) { - Log.e(TAG, "Failed to connect to statsmanager " - + "when registering active configs listener."); - throw new StatsUnavailableException("could not connect", e); - } catch (SecurityException e) { - throw new StatsUnavailableException(e.getMessage(), e); - } - } - } - - // TODO: Temporary for backwards compatibility. Remove. - /** - * @deprecated Use {@link #setFetchReportsOperation(PendingIntent, long)} - */ - @Deprecated - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public boolean setDataFetchOperation(long configKey, PendingIntent pendingIntent) { - try { - setFetchReportsOperation(pendingIntent, configKey); - return true; - } catch (StatsUnavailableException e) { - return false; - } - } - - /** - * Request the data collected for the given configKey. - * This getter is destructive - it also clears the retrieved metrics from statsd's memory. - * - * @param configKey Configuration key to retrieve data from. - * @return Serialized ConfigMetricsReportList proto. - * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service - */ - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public byte[] getReports(long configKey) throws StatsUnavailableException { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - return service.getData(configKey, mContext.getOpPackageName()); - } catch (RemoteException e) { - Log.e(TAG, "Failed to connect to statsmanager when getting data"); - throw new StatsUnavailableException("could not connect", e); - } catch (SecurityException e) { - throw new StatsUnavailableException(e.getMessage(), e); - } catch (IllegalStateException e) { - Log.e(TAG, "Failed to getReports in statsmanager"); - throw new StatsUnavailableException(e.getMessage(), e); - } - } - } - - // TODO: Temporary for backwards compatibility. Remove. - /** - * @deprecated Use {@link #getReports(long)} - */ - @Deprecated - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public @Nullable byte[] getData(long configKey) { - try { - return getReports(configKey); - } catch (StatsUnavailableException e) { - return null; - } - } - - /** - * Clients can request metadata for statsd. Will contain stats across all configurations but not - * the actual metrics themselves (metrics must be collected via {@link #getReports(long)}. - * This getter is not destructive and will not reset any metrics/counters. - * - * @return Serialized StatsdStatsReport proto. - * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service - */ - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public byte[] getStatsMetadata() throws StatsUnavailableException { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - return service.getMetadata(mContext.getOpPackageName()); - } catch (RemoteException e) { - Log.e(TAG, "Failed to connect to statsmanager when getting metadata"); - throw new StatsUnavailableException("could not connect", e); - } catch (SecurityException e) { - throw new StatsUnavailableException(e.getMessage(), e); - } catch (IllegalStateException e) { - Log.e(TAG, "Failed to getStatsMetadata in statsmanager"); - throw new StatsUnavailableException(e.getMessage(), e); - } - } - } - - // TODO: Temporary for backwards compatibility. Remove. - /** - * @deprecated Use {@link #getStatsMetadata()} - */ - @Deprecated - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public @Nullable byte[] getMetadata() { - try { - return getStatsMetadata(); - } catch (StatsUnavailableException e) { - return null; - } - } - - /** - * Returns the experiments IDs registered with statsd, or an empty array if there aren't any. - * - * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service - */ - @RequiresPermission(allOf = {DUMP, PACKAGE_USAGE_STATS}) - public long[] getRegisteredExperimentIds() - throws StatsUnavailableException { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - return service.getRegisteredExperimentIds(); - } catch (RemoteException e) { - if (DEBUG) { - Log.d(TAG, - "Failed to connect to StatsManagerService when getting " - + "registered experiment IDs"); - } - throw new StatsUnavailableException("could not connect", e); - } catch (IllegalStateException e) { - Log.e(TAG, "Failed to getRegisteredExperimentIds in statsmanager"); - throw new StatsUnavailableException(e.getMessage(), e); - } - } - } - - /** - * Sets a callback for an atom when that atom is to be pulled. The stats service will - * invoke pullData in the callback when the stats service determines that this atom needs to be - * pulled. This method should not be called by third-party apps. - * - * @param atomTag The tag of the atom for this puller callback. - * @param metadata Optional metadata specifying the timeout, cool down time, and - * additive fields for mapping isolated to host uids. - * @param executor The executor in which to run the callback. - * @param callback The callback to be invoked when the stats service pulls the atom. - * - */ - @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM) - public void setPullAtomCallback(int atomTag, @Nullable PullAtomMetadata metadata, - @NonNull @CallbackExecutor Executor executor, - @NonNull StatsPullAtomCallback callback) { - long coolDownMillis = - metadata == null ? DEFAULT_COOL_DOWN_MILLIS : metadata.mCoolDownMillis; - long timeoutMillis = metadata == null ? DEFAULT_TIMEOUT_MILLIS : metadata.mTimeoutMillis; - int[] additiveFields = metadata == null ? new int[0] : metadata.mAdditiveFields; - if (additiveFields == null) { - additiveFields = new int[0]; - } - - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - PullAtomCallbackInternal rec = - new PullAtomCallbackInternal(atomTag, callback, executor); - service.registerPullAtomCallback( - atomTag, coolDownMillis, timeoutMillis, additiveFields, rec); - } catch (RemoteException e) { - throw new RuntimeException("Unable to register pull callback", e); - } - } - } - - /** - * Clears a callback for an atom when that atom is to be pulled. Note that any ongoing - * pulls will still occur. This method should not be called by third-party apps. - * - * @param atomTag The tag of the atom of which to unregister - * - */ - @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM) - public void clearPullAtomCallback(int atomTag) { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - service.unregisterPullAtomCallback(atomTag); - } catch (RemoteException e) { - throw new RuntimeException("Unable to unregister pull atom callback"); - } - } - } - - private static class PullAtomCallbackInternal extends IPullAtomCallback.Stub { - public final int mAtomId; - public final StatsPullAtomCallback mCallback; - public final Executor mExecutor; - - PullAtomCallbackInternal(int atomId, StatsPullAtomCallback callback, Executor executor) { - mAtomId = atomId; - mCallback = callback; - mExecutor = executor; - } - - @Override - public void onPullAtom(int atomTag, IPullAtomResultReceiver resultReceiver) { - final long token = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> { - List<StatsEvent> data = new ArrayList<>(); - int successInt = mCallback.onPullAtom(atomTag, data); - boolean success = successInt == PULL_SUCCESS; - StatsEventParcel[] parcels = new StatsEventParcel[data.size()]; - for (int i = 0; i < data.size(); i++) { - parcels[i] = new StatsEventParcel(); - parcels[i].buffer = data.get(i).getBytes(); - } - try { - resultReceiver.pullFinished(atomTag, success, parcels); - } catch (RemoteException e) { - Log.w(TAG, "StatsPullResultReceiver failed for tag " + mAtomId - + " due to TransactionTooLarge. Calling pullFinish with no data"); - StatsEventParcel[] emptyData = new StatsEventParcel[0]; - try { - resultReceiver.pullFinished(atomTag, /*success=*/false, emptyData); - } catch (RemoteException nestedException) { - Log.w(TAG, "StatsPullResultReceiver failed for tag " + mAtomId - + " with empty payload"); - } - } - }); - } finally { - Binder.restoreCallingIdentity(token); - } - } - } - - /** - * Metadata required for registering a StatsPullAtomCallback. - * All fields are optional, and defaults will be used for fields that are unspecified. - * - */ - public static class PullAtomMetadata { - private final long mCoolDownMillis; - private final long mTimeoutMillis; - private final int[] mAdditiveFields; - - // Private Constructor for builder - private PullAtomMetadata(long coolDownMillis, long timeoutMillis, int[] additiveFields) { - mCoolDownMillis = coolDownMillis; - mTimeoutMillis = timeoutMillis; - mAdditiveFields = additiveFields; - } - - /** - * Builder for PullAtomMetadata. - */ - public static class Builder { - private long mCoolDownMillis; - private long mTimeoutMillis; - private int[] mAdditiveFields; - - /** - * Returns a new PullAtomMetadata.Builder object for constructing PullAtomMetadata for - * StatsManager#registerPullAtomCallback - */ - public Builder() { - mCoolDownMillis = DEFAULT_COOL_DOWN_MILLIS; - mTimeoutMillis = DEFAULT_TIMEOUT_MILLIS; - mAdditiveFields = null; - } - - /** - * Set the cool down time of the pull in milliseconds. If two successive pulls are - * issued within the cool down, a cached version of the first pull will be used for the - * second pull. The minimum allowed cool down is 1 second. - */ - @NonNull - public Builder setCoolDownMillis(long coolDownMillis) { - mCoolDownMillis = coolDownMillis; - return this; - } - - /** - * Set the maximum time the pull can take in milliseconds. The maximum allowed timeout - * is 10 seconds. - */ - @NonNull - public Builder setTimeoutMillis(long timeoutMillis) { - mTimeoutMillis = timeoutMillis; - return this; - } - - /** - * Set the additive fields of this pulled atom. - * - * This is only applicable for atoms which have a uid field. When tasks are run in - * isolated processes, the data will be attributed to the host uid. Additive fields - * will be combined when the non-additive fields are the same. - */ - @NonNull - public Builder setAdditiveFields(@NonNull int[] additiveFields) { - mAdditiveFields = additiveFields; - return this; - } - - /** - * Builds and returns a PullAtomMetadata object with the values set in the builder and - * defaults for unset fields. - */ - @NonNull - public PullAtomMetadata build() { - return new PullAtomMetadata(mCoolDownMillis, mTimeoutMillis, mAdditiveFields); - } - } - - /** - * Return the cool down time of this pull in milliseconds. - */ - public long getCoolDownMillis() { - return mCoolDownMillis; - } - - /** - * Return the maximum amount of time this pull can take in milliseconds. - */ - public long getTimeoutMillis() { - return mTimeoutMillis; - } - - /** - * Return the additive fields of this pulled atom. - * - * This is only applicable for atoms that have a uid field. When tasks are run in - * isolated processes, the data will be attributed to the host uid. Additive fields - * will be combined when the non-additive fields are the same. - */ - @Nullable - public int[] getAdditiveFields() { - return mAdditiveFields; - } - } - - /** - * Callback interface for pulling atoms requested by the stats service. - * - */ - public interface StatsPullAtomCallback { - /** - * Pull data for the specified atom tag, filling in the provided list of StatsEvent data. - * @return {@link #PULL_SUCCESS} if the pull was successful, or {@link #PULL_SKIP} if not. - */ - int onPullAtom(int atomTag, @NonNull List<StatsEvent> data); - } - - @GuardedBy("sLock") - private IStatsManagerService getIStatsManagerServiceLocked() { - if (mStatsManagerService != null) { - return mStatsManagerService; - } - mStatsManagerService = IStatsManagerService.Stub.asInterface( - StatsFrameworkInitializer - .getStatsServiceManager() - .getStatsManagerServiceRegisterer() - .get()); - return mStatsManagerService; - } - - /** - * Exception thrown when communication with the stats service fails (eg if it is not available). - * This might be thrown early during boot before the stats service has started or if it crashed. - */ - public static class StatsUnavailableException extends AndroidException { - public StatsUnavailableException(String reason) { - super("Failed to connect to statsd: " + reason); - } - - public StatsUnavailableException(String reason, Throwable e) { - super("Failed to connect to statsd: " + reason, e); - } - } -} diff --git a/apex/statsd/framework/java/android/os/StatsDimensionsValue.java b/apex/statsd/framework/java/android/os/StatsDimensionsValue.java deleted file mode 100644 index 7d9349cefa48..000000000000 --- a/apex/statsd/framework/java/android/os/StatsDimensionsValue.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright 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.annotation.SystemApi; -import android.util.Log; - -import java.util.ArrayList; -import java.util.List; - -/** - * Container for statsd dimension value information, corresponding to a - * stats_log.proto's DimensionValue. - * - * This consists of a field (an int representing a statsd atom field) - * and a value (which may be one of a number of types). - * - * <p> - * Only a single value is held, and it is necessarily one of the following types: - * {@link String}, int, long, boolean, float, - * or tuple (i.e. {@link List} of {@code StatsDimensionsValue}). - * - * The type of value held can be retrieved using {@link #getValueType()}, which returns one of the - * following ints, depending on the type of value: - * <ul> - * <li>{@link #STRING_VALUE_TYPE}</li> - * <li>{@link #INT_VALUE_TYPE}</li> - * <li>{@link #LONG_VALUE_TYPE}</li> - * <li>{@link #BOOLEAN_VALUE_TYPE}</li> - * <li>{@link #FLOAT_VALUE_TYPE}</li> - * <li>{@link #TUPLE_VALUE_TYPE}</li> - * </ul> - * Alternatively, this can be determined using {@link #isValueType(int)} with one of these constants - * as a parameter. - * The value itself can be retrieved using the correct get...Value() function for its type. - * - * <p> - * The field is always an int, and always exists; it can be obtained using {@link #getField()}. - * - * - * @hide - */ -@SystemApi -public final class StatsDimensionsValue implements Parcelable { - private static final String TAG = "StatsDimensionsValue"; - - // Values of the value type correspond to stats_log.proto's DimensionValue fields. - // Keep constants in sync with frameworks/base/cmds/statsd/src/HashableDimensionKey.cpp. - /** Indicates that this holds a String. */ - public static final int STRING_VALUE_TYPE = 2; - /** Indicates that this holds an int. */ - public static final int INT_VALUE_TYPE = 3; - /** Indicates that this holds a long. */ - public static final int LONG_VALUE_TYPE = 4; - /** Indicates that this holds a boolean. */ - public static final int BOOLEAN_VALUE_TYPE = 5; - /** Indicates that this holds a float. */ - public static final int FLOAT_VALUE_TYPE = 6; - /** Indicates that this holds a List of StatsDimensionsValues. */ - public static final int TUPLE_VALUE_TYPE = 7; - - private final StatsDimensionsValueParcel mInner; - - /** - * Creates a {@code StatsDimensionValue} from a parcel. - * - * @hide - */ - public StatsDimensionsValue(Parcel in) { - mInner = StatsDimensionsValueParcel.CREATOR.createFromParcel(in); - } - - /** - * Creates a {@code StatsDimensionsValue} from a StatsDimensionsValueParcel - * - * @hide - */ - public StatsDimensionsValue(StatsDimensionsValueParcel parcel) { - mInner = parcel; - } - - /** - * Return the field, i.e. the tag of a statsd atom. - * - * @return the field - */ - public int getField() { - return mInner.field; - } - - /** - * Retrieve the String held, if any. - * - * @return the {@link String} held if {@link #getValueType()} == {@link #STRING_VALUE_TYPE}, - * null otherwise - */ - public String getStringValue() { - if (mInner.valueType == STRING_VALUE_TYPE) { - return mInner.stringValue; - } else { - Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not string."); - return null; - } - } - - /** - * Retrieve the int held, if any. - * - * @return the int held if {@link #getValueType()} == {@link #INT_VALUE_TYPE}, 0 otherwise - */ - public int getIntValue() { - if (mInner.valueType == INT_VALUE_TYPE) { - return mInner.intValue; - } else { - Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not int."); - return 0; - } - } - - /** - * Retrieve the long held, if any. - * - * @return the long held if {@link #getValueType()} == {@link #LONG_VALUE_TYPE}, 0 otherwise - */ - public long getLongValue() { - if (mInner.valueType == LONG_VALUE_TYPE) { - return mInner.longValue; - } else { - Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not long."); - return 0; - } - } - - /** - * Retrieve the boolean held, if any. - * - * @return the boolean held if {@link #getValueType()} == {@link #BOOLEAN_VALUE_TYPE}, - * false otherwise - */ - public boolean getBooleanValue() { - if (mInner.valueType == BOOLEAN_VALUE_TYPE) { - return mInner.boolValue; - } else { - Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not boolean."); - return false; - } - } - - /** - * Retrieve the float held, if any. - * - * @return the float held if {@link #getValueType()} == {@link #FLOAT_VALUE_TYPE}, 0 otherwise - */ - public float getFloatValue() { - if (mInner.valueType == FLOAT_VALUE_TYPE) { - return mInner.floatValue; - } else { - Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not float."); - return 0; - } - } - - /** - * Retrieve the tuple, in the form of a {@link List} of {@link StatsDimensionsValue}, held, - * if any. - * - * @return the {@link List} of {@link StatsDimensionsValue} held - * if {@link #getValueType()} == {@link #TUPLE_VALUE_TYPE}, - * null otherwise - */ - public List<StatsDimensionsValue> getTupleValueList() { - if (mInner.valueType == TUPLE_VALUE_TYPE) { - int length = (mInner.tupleValue == null) ? 0 : mInner.tupleValue.length; - List<StatsDimensionsValue> tupleValues = new ArrayList<>(length); - for (int i = 0; i < length; i++) { - tupleValues.add(new StatsDimensionsValue(mInner.tupleValue[i])); - } - return tupleValues; - } else { - Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not tuple."); - return null; - } - } - - /** - * Returns the constant representing the type of value stored, namely one of - * <ul> - * <li>{@link #STRING_VALUE_TYPE}</li> - * <li>{@link #INT_VALUE_TYPE}</li> - * <li>{@link #LONG_VALUE_TYPE}</li> - * <li>{@link #BOOLEAN_VALUE_TYPE}</li> - * <li>{@link #FLOAT_VALUE_TYPE}</li> - * <li>{@link #TUPLE_VALUE_TYPE}</li> - * </ul> - * - * @return the constant representing the type of value stored - */ - public int getValueType() { - return mInner.valueType; - } - - /** - * Returns whether the type of value stored is equal to the given type. - * - * @param valueType int representing the type of value stored, as used in {@link #getValueType} - * @return true if {@link #getValueType()} is equal to {@code valueType}. - */ - public boolean isValueType(int valueType) { - return mInner.valueType == valueType; - } - - /** - * Returns a String representing the information in this StatsDimensionValue. - * No guarantees are made about the format of this String. - * - * @return String representation - * - * @hide - */ - // Follows the format of statsd's dimension.h toString. - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(mInner.field); - sb.append(":"); - switch (mInner.valueType) { - case STRING_VALUE_TYPE: - sb.append(mInner.stringValue); - break; - case INT_VALUE_TYPE: - sb.append(String.valueOf(mInner.intValue)); - break; - case LONG_VALUE_TYPE: - sb.append(String.valueOf(mInner.longValue)); - break; - case BOOLEAN_VALUE_TYPE: - sb.append(String.valueOf(mInner.boolValue)); - break; - case FLOAT_VALUE_TYPE: - sb.append(String.valueOf(mInner.floatValue)); - break; - case TUPLE_VALUE_TYPE: - sb.append("{"); - int length = (mInner.tupleValue == null) ? 0 : mInner.tupleValue.length; - for (int i = 0; i < length; i++) { - StatsDimensionsValue child = new StatsDimensionsValue(mInner.tupleValue[i]); - sb.append(child.toString()); - sb.append("|"); - } - sb.append("}"); - break; - default: - Log.w(TAG, "Incorrect value type"); - break; - } - return sb.toString(); - } - - /** - * Parcelable Creator for StatsDimensionsValue. - */ - public static final @android.annotation.NonNull - Parcelable.Creator<StatsDimensionsValue> CREATOR = new - Parcelable.Creator<StatsDimensionsValue>() { - public StatsDimensionsValue createFromParcel(Parcel in) { - return new StatsDimensionsValue(in); - } - - public StatsDimensionsValue[] newArray(int size) { - return new StatsDimensionsValue[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - mInner.writeToParcel(out, flags); - } - - /** - * Returns a string representation of the type of value stored. - */ - private String getValueTypeAsString() { - switch (mInner.valueType) { - case STRING_VALUE_TYPE: - return "string"; - case INT_VALUE_TYPE: - return "int"; - case LONG_VALUE_TYPE: - return "long"; - case BOOLEAN_VALUE_TYPE: - return "boolean"; - case FLOAT_VALUE_TYPE: - return "float"; - case TUPLE_VALUE_TYPE: - return "tuple"; - default: - return "unknown"; - } - } -} diff --git a/apex/statsd/framework/java/android/os/StatsFrameworkInitializer.java b/apex/statsd/framework/java/android/os/StatsFrameworkInitializer.java deleted file mode 100644 index 8dc91239c2e0..000000000000 --- a/apex/statsd/framework/java/android/os/StatsFrameworkInitializer.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.os; - -import android.annotation.NonNull; -import android.annotation.SystemApi; -import android.annotation.SystemApi.Client; -import android.app.StatsManager; -import android.app.SystemServiceRegistry; -import android.content.Context; - -/** - * Class for performing registration for all stats services - * - * @hide - */ -@SystemApi(client = Client.MODULE_LIBRARIES) -public class StatsFrameworkInitializer { - private StatsFrameworkInitializer() { - } - - private static volatile StatsServiceManager sStatsServiceManager; - - /** - * Sets an instance of {@link StatsServiceManager} that allows - * the statsd mainline module to register/obtain stats binder services. This is called - * by the platform during the system initialization. - * - * @param statsServiceManager instance of {@link StatsServiceManager} that allows - * the statsd mainline module to register/obtain statsd binder services. - */ - public static void setStatsServiceManager( - @NonNull StatsServiceManager statsServiceManager) { - if (sStatsServiceManager != null) { - throw new IllegalStateException("setStatsServiceManager called twice!"); - } - - if (statsServiceManager == null) { - throw new NullPointerException("statsServiceManager is null"); - } - - sStatsServiceManager = statsServiceManager; - } - - /** @hide */ - public static StatsServiceManager getStatsServiceManager() { - return sStatsServiceManager; - } - - /** - * Called by {@link SystemServiceRegistry}'s static initializer and registers all statsd - * services to {@link Context}, so that {@link Context#getSystemService} can return them. - * - * @throws IllegalStateException if this is called from anywhere besides - * {@link SystemServiceRegistry} - */ - public static void registerServiceWrappers() { - SystemServiceRegistry.registerContextAwareService( - Context.STATS_MANAGER, - StatsManager.class, - context -> new StatsManager(context) - ); - } -} diff --git a/apex/statsd/framework/java/android/util/StatsEvent.java b/apex/statsd/framework/java/android/util/StatsEvent.java deleted file mode 100644 index 8be5c63f31e3..000000000000 --- a/apex/statsd/framework/java/android/util/StatsEvent.java +++ /dev/null @@ -1,879 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.util; - -import static java.nio.charset.StandardCharsets.UTF_8; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.os.SystemClock; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; - -import java.util.Arrays; - -/** - * StatsEvent builds and stores the buffer sent over the statsd socket. - * This class defines and encapsulates the socket protocol. - * - * <p>Usage:</p> - * <pre> - * // Pushed event - * StatsEvent statsEvent = StatsEvent.newBuilder() - * .setAtomId(atomId) - * .writeBoolean(false) - * .writeString("annotated String field") - * .addBooleanAnnotation(annotationId, true) - * .usePooledBuffer() - * .build(); - * StatsLog.write(statsEvent); - * - * // Pulled event - * StatsEvent statsEvent = StatsEvent.newBuilder() - * .setAtomId(atomId) - * .writeBoolean(false) - * .writeString("annotated String field") - * .addBooleanAnnotation(annotationId, true) - * .build(); - * </pre> - * @hide - **/ -@SystemApi -public final class StatsEvent { - // Type Ids. - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_INT = 0x00; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_LONG = 0x01; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_STRING = 0x02; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_LIST = 0x03; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_FLOAT = 0x04; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_BOOLEAN = 0x05; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_BYTE_ARRAY = 0x06; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_OBJECT = 0x07; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_KEY_VALUE_PAIRS = 0x08; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_ATTRIBUTION_CHAIN = 0x09; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_ERRORS = 0x0F; - - // Error flags. - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_NO_TIMESTAMP = 0x1; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_NO_ATOM_ID = 0x2; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_OVERFLOW = 0x4; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_ATTRIBUTION_CHAIN_TOO_LONG = 0x8; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_TOO_MANY_KEY_VALUE_PAIRS = 0x10; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD = 0x20; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_INVALID_ANNOTATION_ID = 0x40; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_ANNOTATION_ID_TOO_LARGE = 0x80; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_TOO_MANY_ANNOTATIONS = 0x100; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_TOO_MANY_FIELDS = 0x200; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL = 0x1000; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_ATOM_ID_INVALID_POSITION = 0x2000; - - // Size limits. - - /** - * @hide - **/ - @VisibleForTesting - public static final int MAX_ANNOTATION_COUNT = 15; - - /** - * @hide - **/ - @VisibleForTesting - public static final int MAX_ATTRIBUTION_NODES = 127; - - /** - * @hide - **/ - @VisibleForTesting - public static final int MAX_NUM_ELEMENTS = 127; - - /** - * @hide - **/ - @VisibleForTesting - public static final int MAX_KEY_VALUE_PAIRS = 127; - - private static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068; - - // Max payload size is 4 bytes less as 4 bytes are reserved for statsEventTag. - // See android_util_StatsLog.cpp. - private static final int MAX_PUSH_PAYLOAD_SIZE = LOGGER_ENTRY_MAX_PAYLOAD - 4; - - private static final int MAX_PULL_PAYLOAD_SIZE = 50 * 1024; // 50 KB - - private final int mAtomId; - private final byte[] mPayload; - private Buffer mBuffer; - private final int mNumBytes; - - private StatsEvent(final int atomId, @Nullable final Buffer buffer, - @NonNull final byte[] payload, final int numBytes) { - mAtomId = atomId; - mBuffer = buffer; - mPayload = payload; - mNumBytes = numBytes; - } - - /** - * Returns a new StatsEvent.Builder for building StatsEvent object. - **/ - @NonNull - public static StatsEvent.Builder newBuilder() { - return new StatsEvent.Builder(Buffer.obtain()); - } - - /** - * Get the atom Id of the atom encoded in this StatsEvent object. - * - * @hide - **/ - public int getAtomId() { - return mAtomId; - } - - /** - * Get the byte array that contains the encoded payload that can be sent to statsd. - * - * @hide - **/ - @NonNull - public byte[] getBytes() { - return mPayload; - } - - /** - * Get the number of bytes used to encode the StatsEvent payload. - * - * @hide - **/ - public int getNumBytes() { - return mNumBytes; - } - - /** - * Recycle resources used by this StatsEvent object. - * No actions should be taken on this StatsEvent after release() is called. - * - * @hide - **/ - public void release() { - if (mBuffer != null) { - mBuffer.release(); - mBuffer = null; - } - } - - /** - * Builder for constructing a StatsEvent object. - * - * <p>This class defines and encapsulates the socket encoding for the buffer. - * The write methods must be called in the same order as the order of fields in the - * atom definition.</p> - * - * <p>setAtomId() can be called anytime before build().</p> - * - * <p>Example:</p> - * <pre> - * // Atom definition. - * message MyAtom { - * optional int32 field1 = 1; - * optional int64 field2 = 2; - * optional string field3 = 3 [(annotation1) = true]; - * } - * - * // StatsEvent construction for pushed event. - * StatsEvent.newBuilder() - * StatsEvent statsEvent = StatsEvent.newBuilder() - * .setAtomId(atomId) - * .writeInt(3) // field1 - * .writeLong(8L) // field2 - * .writeString("foo") // field 3 - * .addBooleanAnnotation(annotation1Id, true) - * .usePooledBuffer() - * .build(); - * - * // StatsEvent construction for pulled event. - * StatsEvent.newBuilder() - * StatsEvent statsEvent = StatsEvent.newBuilder() - * .setAtomId(atomId) - * .writeInt(3) // field1 - * .writeLong(8L) // field2 - * .writeString("foo") // field 3 - * .addBooleanAnnotation(annotation1Id, true) - * .build(); - * </pre> - **/ - public static final class Builder { - // Fixed positions. - private static final int POS_NUM_ELEMENTS = 1; - private static final int POS_TIMESTAMP_NS = POS_NUM_ELEMENTS + Byte.BYTES; - private static final int POS_ATOM_ID = POS_TIMESTAMP_NS + Byte.BYTES + Long.BYTES; - - private final Buffer mBuffer; - private long mTimestampNs; - private int mAtomId; - private byte mCurrentAnnotationCount; - private int mPos; - private int mPosLastField; - private byte mLastType; - private int mNumElements; - private int mErrorMask; - private boolean mUsePooledBuffer = false; - - private Builder(final Buffer buffer) { - mBuffer = buffer; - mCurrentAnnotationCount = 0; - mAtomId = 0; - mTimestampNs = SystemClock.elapsedRealtimeNanos(); - mNumElements = 0; - - // Set mPos to 0 for writing TYPE_OBJECT at 0th position. - mPos = 0; - writeTypeId(TYPE_OBJECT); - - // Write timestamp. - mPos = POS_TIMESTAMP_NS; - writeLong(mTimestampNs); - } - - /** - * Sets the atom id for this StatsEvent. - * - * This should be called immediately after StatsEvent.newBuilder() - * and should only be called once. - * Not calling setAtomId will result in ERROR_NO_ATOM_ID. - * Calling setAtomId out of order will result in ERROR_ATOM_ID_INVALID_POSITION. - **/ - @NonNull - public Builder setAtomId(final int atomId) { - if (0 == mAtomId) { - mAtomId = atomId; - - if (1 == mNumElements) { // Only timestamp is written so far. - writeInt(atomId); - } else { - // setAtomId called out of order. - mErrorMask |= ERROR_ATOM_ID_INVALID_POSITION; - } - } - - return this; - } - - /** - * Write a boolean field to this StatsEvent. - **/ - @NonNull - public Builder writeBoolean(final boolean value) { - // Write boolean typeId byte followed by boolean byte representation. - writeTypeId(TYPE_BOOLEAN); - mPos += mBuffer.putBoolean(mPos, value); - mNumElements++; - return this; - } - - /** - * Write an integer field to this StatsEvent. - **/ - @NonNull - public Builder writeInt(final int value) { - // Write integer typeId byte followed by 4-byte representation of value. - writeTypeId(TYPE_INT); - mPos += mBuffer.putInt(mPos, value); - mNumElements++; - return this; - } - - /** - * Write a long field to this StatsEvent. - **/ - @NonNull - public Builder writeLong(final long value) { - // Write long typeId byte followed by 8-byte representation of value. - writeTypeId(TYPE_LONG); - mPos += mBuffer.putLong(mPos, value); - mNumElements++; - return this; - } - - /** - * Write a float field to this StatsEvent. - **/ - @NonNull - public Builder writeFloat(final float value) { - // Write float typeId byte followed by 4-byte representation of value. - writeTypeId(TYPE_FLOAT); - mPos += mBuffer.putFloat(mPos, value); - mNumElements++; - return this; - } - - /** - * Write a String field to this StatsEvent. - **/ - @NonNull - public Builder writeString(@NonNull final String value) { - // Write String typeId byte, followed by 4-byte representation of number of bytes - // in the UTF-8 encoding, followed by the actual UTF-8 byte encoding of value. - final byte[] valueBytes = stringToBytes(value); - writeByteArray(valueBytes, TYPE_STRING); - return this; - } - - /** - * Write a byte array field to this StatsEvent. - **/ - @NonNull - public Builder writeByteArray(@NonNull final byte[] value) { - // Write byte array typeId byte, followed by 4-byte representation of number of bytes - // in value, followed by the actual byte array. - writeByteArray(value, TYPE_BYTE_ARRAY); - return this; - } - - private void writeByteArray(@NonNull final byte[] value, final byte typeId) { - writeTypeId(typeId); - final int numBytes = value.length; - mPos += mBuffer.putInt(mPos, numBytes); - mPos += mBuffer.putByteArray(mPos, value); - mNumElements++; - } - - /** - * Write an attribution chain field to this StatsEvent. - * - * The sizes of uids and tags must be equal. The AttributionNode at position i is - * made up of uids[i] and tags[i]. - * - * @param uids array of uids in the attribution nodes. - * @param tags array of tags in the attribution nodes. - **/ - @NonNull - public Builder writeAttributionChain( - @NonNull final int[] uids, @NonNull final String[] tags) { - final byte numUids = (byte) uids.length; - final byte numTags = (byte) tags.length; - - if (numUids != numTags) { - mErrorMask |= ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL; - } else if (numUids > MAX_ATTRIBUTION_NODES) { - mErrorMask |= ERROR_ATTRIBUTION_CHAIN_TOO_LONG; - } else { - // Write attribution chain typeId byte, followed by 1-byte representation of - // number of attribution nodes, followed by encoding of each attribution node. - writeTypeId(TYPE_ATTRIBUTION_CHAIN); - mPos += mBuffer.putByte(mPos, numUids); - for (int i = 0; i < numUids; i++) { - // Each uid is encoded as 4-byte representation of its int value. - mPos += mBuffer.putInt(mPos, uids[i]); - - // Each tag is encoded as 4-byte representation of number of bytes in its - // UTF-8 encoding, followed by the actual UTF-8 bytes. - final byte[] tagBytes = stringToBytes(tags[i]); - mPos += mBuffer.putInt(mPos, tagBytes.length); - mPos += mBuffer.putByteArray(mPos, tagBytes); - } - mNumElements++; - } - return this; - } - - /** - * Write KeyValuePairsAtom entries to this StatsEvent. - * - * @param intMap Integer key-value pairs. - * @param longMap Long key-value pairs. - * @param stringMap String key-value pairs. - * @param floatMap Float key-value pairs. - **/ - @NonNull - public Builder writeKeyValuePairs( - @Nullable final SparseIntArray intMap, - @Nullable final SparseLongArray longMap, - @Nullable final SparseArray<String> stringMap, - @Nullable final SparseArray<Float> floatMap) { - final int intMapSize = null == intMap ? 0 : intMap.size(); - final int longMapSize = null == longMap ? 0 : longMap.size(); - final int stringMapSize = null == stringMap ? 0 : stringMap.size(); - final int floatMapSize = null == floatMap ? 0 : floatMap.size(); - final int totalCount = intMapSize + longMapSize + stringMapSize + floatMapSize; - - if (totalCount > MAX_KEY_VALUE_PAIRS) { - mErrorMask |= ERROR_TOO_MANY_KEY_VALUE_PAIRS; - } else { - writeTypeId(TYPE_KEY_VALUE_PAIRS); - mPos += mBuffer.putByte(mPos, (byte) totalCount); - - for (int i = 0; i < intMapSize; i++) { - final int key = intMap.keyAt(i); - final int value = intMap.valueAt(i); - mPos += mBuffer.putInt(mPos, key); - writeTypeId(TYPE_INT); - mPos += mBuffer.putInt(mPos, value); - } - - for (int i = 0; i < longMapSize; i++) { - final int key = longMap.keyAt(i); - final long value = longMap.valueAt(i); - mPos += mBuffer.putInt(mPos, key); - writeTypeId(TYPE_LONG); - mPos += mBuffer.putLong(mPos, value); - } - - for (int i = 0; i < stringMapSize; i++) { - final int key = stringMap.keyAt(i); - final String value = stringMap.valueAt(i); - mPos += mBuffer.putInt(mPos, key); - writeTypeId(TYPE_STRING); - final byte[] valueBytes = stringToBytes(value); - mPos += mBuffer.putInt(mPos, valueBytes.length); - mPos += mBuffer.putByteArray(mPos, valueBytes); - } - - for (int i = 0; i < floatMapSize; i++) { - final int key = floatMap.keyAt(i); - final float value = floatMap.valueAt(i); - mPos += mBuffer.putInt(mPos, key); - writeTypeId(TYPE_FLOAT); - mPos += mBuffer.putFloat(mPos, value); - } - - mNumElements++; - } - - return this; - } - - /** - * Write a boolean annotation for the last field written. - **/ - @NonNull - public Builder addBooleanAnnotation( - final byte annotationId, final boolean value) { - // Ensure there's a field written to annotate. - if (mNumElements < 2) { - mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD; - } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) { - mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS; - } else { - mPos += mBuffer.putByte(mPos, annotationId); - mPos += mBuffer.putByte(mPos, TYPE_BOOLEAN); - mPos += mBuffer.putBoolean(mPos, value); - mCurrentAnnotationCount++; - writeAnnotationCount(); - } - - return this; - } - - /** - * Write an integer annotation for the last field written. - **/ - @NonNull - public Builder addIntAnnotation(final byte annotationId, final int value) { - if (mNumElements < 2) { - mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD; - } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) { - mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS; - } else { - mPos += mBuffer.putByte(mPos, annotationId); - mPos += mBuffer.putByte(mPos, TYPE_INT); - mPos += mBuffer.putInt(mPos, value); - mCurrentAnnotationCount++; - writeAnnotationCount(); - } - - return this; - } - - /** - * Indicates to reuse Buffer's byte array as the underlying payload in StatsEvent. - * This should be called for pushed events to reduce memory allocations and garbage - * collections. - **/ - @NonNull - public Builder usePooledBuffer() { - mUsePooledBuffer = true; - mBuffer.setMaxSize(MAX_PUSH_PAYLOAD_SIZE, mPos); - return this; - } - - /** - * Builds a StatsEvent object with values entered in this Builder. - **/ - @NonNull - public StatsEvent build() { - if (0L == mTimestampNs) { - mErrorMask |= ERROR_NO_TIMESTAMP; - } - if (0 == mAtomId) { - mErrorMask |= ERROR_NO_ATOM_ID; - } - if (mBuffer.hasOverflowed()) { - mErrorMask |= ERROR_OVERFLOW; - } - if (mNumElements > MAX_NUM_ELEMENTS) { - mErrorMask |= ERROR_TOO_MANY_FIELDS; - } - - if (0 == mErrorMask) { - mBuffer.putByte(POS_NUM_ELEMENTS, (byte) mNumElements); - } else { - // Write atom id and error mask. Overwrite any annotations for atom Id. - mPos = POS_ATOM_ID; - mPos += mBuffer.putByte(mPos, TYPE_INT); - mPos += mBuffer.putInt(mPos, mAtomId); - mPos += mBuffer.putByte(mPos, TYPE_ERRORS); - mPos += mBuffer.putInt(mPos, mErrorMask); - mBuffer.putByte(POS_NUM_ELEMENTS, (byte) 3); - } - - final int size = mPos; - - if (mUsePooledBuffer) { - return new StatsEvent(mAtomId, mBuffer, mBuffer.getBytes(), size); - } else { - // Create a copy of the buffer with the required number of bytes. - final byte[] payload = new byte[size]; - System.arraycopy(mBuffer.getBytes(), 0, payload, 0, size); - - // Return Buffer instance to the pool. - mBuffer.release(); - - return new StatsEvent(mAtomId, null, payload, size); - } - } - - private void writeTypeId(final byte typeId) { - mPosLastField = mPos; - mLastType = typeId; - mCurrentAnnotationCount = 0; - final byte encodedId = (byte) (typeId & 0x0F); - mPos += mBuffer.putByte(mPos, encodedId); - } - - private void writeAnnotationCount() { - // Use first 4 bits for annotation count and last 4 bits for typeId. - final byte encodedId = (byte) ((mCurrentAnnotationCount << 4) | (mLastType & 0x0F)); - mBuffer.putByte(mPosLastField, encodedId); - } - - @NonNull - private static byte[] stringToBytes(@Nullable final String value) { - return (null == value ? "" : value).getBytes(UTF_8); - } - } - - private static final class Buffer { - private static Object sLock = new Object(); - - @GuardedBy("sLock") - private static Buffer sPool; - - private byte[] mBytes = new byte[MAX_PUSH_PAYLOAD_SIZE]; - private boolean mOverflow = false; - private int mMaxSize = MAX_PULL_PAYLOAD_SIZE; - - @NonNull - private static Buffer obtain() { - final Buffer buffer; - synchronized (sLock) { - buffer = null == sPool ? new Buffer() : sPool; - sPool = null; - } - buffer.reset(); - return buffer; - } - - private Buffer() { - } - - @NonNull - private byte[] getBytes() { - return mBytes; - } - - private void release() { - // Recycle this Buffer if its size is MAX_PUSH_PAYLOAD_SIZE or under. - if (mBytes.length <= MAX_PUSH_PAYLOAD_SIZE) { - synchronized (sLock) { - if (null == sPool) { - sPool = this; - } - } - } - } - - private void reset() { - mOverflow = false; - mMaxSize = MAX_PULL_PAYLOAD_SIZE; - } - - private void setMaxSize(final int maxSize, final int numBytesWritten) { - mMaxSize = maxSize; - if (numBytesWritten > maxSize) { - mOverflow = true; - } - } - - private boolean hasOverflowed() { - return mOverflow; - } - - /** - * Checks for available space in the byte array. - * - * @param index starting position in the buffer to start the check. - * @param numBytes number of bytes to check from index. - * @return true if space is available, false otherwise. - **/ - private boolean hasEnoughSpace(final int index, final int numBytes) { - final int totalBytesNeeded = index + numBytes; - - if (totalBytesNeeded > mMaxSize) { - mOverflow = true; - return false; - } - - // Expand buffer if needed. - if (mBytes.length < mMaxSize && totalBytesNeeded > mBytes.length) { - int newSize = mBytes.length; - do { - newSize *= 2; - } while (newSize <= totalBytesNeeded); - - if (newSize > mMaxSize) { - newSize = mMaxSize; - } - - mBytes = Arrays.copyOf(mBytes, newSize); - } - - return true; - } - - /** - * Writes a byte into the buffer. - * - * @param index position in the buffer where the byte is written. - * @param value the byte to write. - * @return number of bytes written to buffer from this write operation. - **/ - private int putByte(final int index, final byte value) { - if (hasEnoughSpace(index, Byte.BYTES)) { - mBytes[index] = (byte) (value); - return Byte.BYTES; - } - return 0; - } - - /** - * Writes a boolean into the buffer. - * - * @param index position in the buffer where the boolean is written. - * @param value the boolean to write. - * @return number of bytes written to buffer from this write operation. - **/ - private int putBoolean(final int index, final boolean value) { - return putByte(index, (byte) (value ? 1 : 0)); - } - - /** - * Writes an integer into the buffer. - * - * @param index position in the buffer where the integer is written. - * @param value the integer to write. - * @return number of bytes written to buffer from this write operation. - **/ - private int putInt(final int index, final int value) { - if (hasEnoughSpace(index, Integer.BYTES)) { - // Use little endian byte order. - mBytes[index] = (byte) (value); - mBytes[index + 1] = (byte) (value >> 8); - mBytes[index + 2] = (byte) (value >> 16); - mBytes[index + 3] = (byte) (value >> 24); - return Integer.BYTES; - } - return 0; - } - - /** - * Writes a long into the buffer. - * - * @param index position in the buffer where the long is written. - * @param value the long to write. - * @return number of bytes written to buffer from this write operation. - **/ - private int putLong(final int index, final long value) { - if (hasEnoughSpace(index, Long.BYTES)) { - // Use little endian byte order. - mBytes[index] = (byte) (value); - mBytes[index + 1] = (byte) (value >> 8); - mBytes[index + 2] = (byte) (value >> 16); - mBytes[index + 3] = (byte) (value >> 24); - mBytes[index + 4] = (byte) (value >> 32); - mBytes[index + 5] = (byte) (value >> 40); - mBytes[index + 6] = (byte) (value >> 48); - mBytes[index + 7] = (byte) (value >> 56); - return Long.BYTES; - } - return 0; - } - - /** - * Writes a float into the buffer. - * - * @param index position in the buffer where the float is written. - * @param value the float to write. - * @return number of bytes written to buffer from this write operation. - **/ - private int putFloat(final int index, final float value) { - return putInt(index, Float.floatToIntBits(value)); - } - - /** - * Copies a byte array into the buffer. - * - * @param index position in the buffer where the byte array is copied. - * @param value the byte array to copy. - * @return number of bytes written to buffer from this write operation. - **/ - private int putByteArray(final int index, @NonNull final byte[] value) { - final int numBytes = value.length; - if (hasEnoughSpace(index, numBytes)) { - System.arraycopy(value, 0, mBytes, index, numBytes); - return numBytes; - } - return 0; - } - } -} diff --git a/apex/statsd/framework/java/android/util/StatsLog.java b/apex/statsd/framework/java/android/util/StatsLog.java deleted file mode 100644 index 0a9f4ebabdf0..000000000000 --- a/apex/statsd/framework/java/android/util/StatsLog.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.util; - -import static android.Manifest.permission.DUMP; -import static android.Manifest.permission.PACKAGE_USAGE_STATS; - -import android.Manifest; -import android.annotation.NonNull; -import android.annotation.RequiresPermission; -import android.annotation.SystemApi; -import android.content.Context; -import android.os.IStatsd; -import android.os.Process; -import android.util.proto.ProtoOutputStream; - -import com.android.internal.statsd.StatsdStatsLog; - -/** - * StatsLog provides an API for developers to send events to statsd. The events can be used to - * define custom metrics inside statsd. - */ -public final class StatsLog { - - // Load JNI library - static { - System.loadLibrary("stats_jni"); - } - private static final String TAG = "StatsLog"; - private static final boolean DEBUG = false; - private static final int EXPERIMENT_IDS_FIELD_ID = 1; - - private StatsLog() { - } - - /** - * Logs a start event. - * - * @param label developer-chosen label. - * @return True if the log request was sent to statsd. - */ - public static boolean logStart(int label) { - int callingUid = Process.myUid(); - StatsdStatsLog.write( - StatsdStatsLog.APP_BREADCRUMB_REPORTED, - callingUid, - label, - StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__START); - return true; - } - - /** - * Logs a stop event. - * - * @param label developer-chosen label. - * @return True if the log request was sent to statsd. - */ - public static boolean logStop(int label) { - int callingUid = Process.myUid(); - StatsdStatsLog.write( - StatsdStatsLog.APP_BREADCRUMB_REPORTED, - callingUid, - label, - StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__STOP); - return true; - } - - /** - * Logs an event that does not represent a start or stop boundary. - * - * @param label developer-chosen label. - * @return True if the log request was sent to statsd. - */ - public static boolean logEvent(int label) { - int callingUid = Process.myUid(); - StatsdStatsLog.write( - StatsdStatsLog.APP_BREADCRUMB_REPORTED, - callingUid, - label, - StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__UNSPECIFIED); - return true; - } - - /** - * Logs an event for binary push for module updates. - * - * @param trainName name of install train. - * @param trainVersionCode version code of the train. - * @param options optional flags about this install. - * The last 3 bits indicate options: - * 0x01: FLAG_REQUIRE_STAGING - * 0x02: FLAG_ROLLBACK_ENABLED - * 0x04: FLAG_REQUIRE_LOW_LATENCY_MONITOR - * @param state current install state. Defined as State enums in - * BinaryPushStateChanged atom in - * frameworks/base/cmds/statsd/src/atoms.proto - * @param experimentIds experiment ids. - * @return True if the log request was sent to statsd. - */ - @RequiresPermission(allOf = {DUMP, PACKAGE_USAGE_STATS}) - public static boolean logBinaryPushStateChanged(@NonNull String trainName, - long trainVersionCode, int options, int state, - @NonNull long[] experimentIds) { - ProtoOutputStream proto = new ProtoOutputStream(); - for (long id : experimentIds) { - proto.write( - ProtoOutputStream.FIELD_TYPE_INT64 - | ProtoOutputStream.FIELD_COUNT_REPEATED - | EXPERIMENT_IDS_FIELD_ID, - id); - } - StatsdStatsLog.write(StatsdStatsLog.BINARY_PUSH_STATE_CHANGED, - trainName, - trainVersionCode, - (options & IStatsd.FLAG_REQUIRE_STAGING) > 0, - (options & IStatsd.FLAG_ROLLBACK_ENABLED) > 0, - (options & IStatsd.FLAG_REQUIRE_LOW_LATENCY_MONITOR) > 0, - state, - proto.getBytes(), - 0, - 0, - false); - return true; - } - - /** - * Write an event to stats log using the raw format. - * - * @param buffer The encoded buffer of data to write. - * @param size The number of bytes from the buffer to write. - * @hide - */ - // TODO(b/144935988): Mark deprecated. - @SystemApi - public static void writeRaw(@NonNull byte[] buffer, int size) { - // TODO(b/144935988): make this no-op once clients have migrated to StatsEvent. - writeImpl(buffer, size, 0); - } - - /** - * Write an event to stats log using the raw format. - * - * @param buffer The encoded buffer of data to write. - * @param size The number of bytes from the buffer to write. - * @param atomId The id of the atom to which the event belongs. - */ - private static native void writeImpl(@NonNull byte[] buffer, int size, int atomId); - - /** - * Write an event to stats log using the raw format encapsulated in StatsEvent. - * After writing to stats log, release() is called on the StatsEvent object. - * No further action should be taken on the StatsEvent object following this call. - * - * @param statsEvent The StatsEvent object containing the encoded buffer of data to write. - * @hide - */ - @SystemApi - public static void write(@NonNull final StatsEvent statsEvent) { - writeImpl(statsEvent.getBytes(), statsEvent.getNumBytes(), statsEvent.getAtomId()); - statsEvent.release(); - } - - private static void enforceDumpCallingPermission(Context context) { - context.enforceCallingPermission(android.Manifest.permission.DUMP, "Need DUMP permission."); - } - - private static void enforcesageStatsCallingPermission(Context context) { - context.enforceCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS, - "Need PACKAGE_USAGE_STATS permission."); - } -} diff --git a/apex/statsd/framework/test/Android.bp b/apex/statsd/framework/test/Android.bp deleted file mode 100644 index 5cc5647bc760..000000000000 --- a/apex/statsd/framework/test/Android.bp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (C) 2020 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -android_test { - name: "FrameworkStatsdTest", - sdk_version: "module_current", - srcs: [ "**/*.java" ], - manifest: "AndroidManifest.xml", - static_libs: [ - "androidx.test.rules", - "truth-prebuilt", - ], - libs: [ - "android.test.runner.stubs", - "android.test.base.stubs", - "framework-statsd.impl", - ], - test_suites: [ - "device-tests", - "mts", - ], -} diff --git a/apex/statsd/framework/test/AndroidManifest.xml b/apex/statsd/framework/test/AndroidManifest.xml deleted file mode 100644 index 8f89d2332b12..000000000000 --- a/apex/statsd/framework/test/AndroidManifest.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2020 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.os.statsd.framework.test" - > - - <instrumentation - android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="com.android.os.statsd.framework.test" - android:label="Framework Statsd Tests" /> - -</manifest> diff --git a/apex/statsd/framework/test/AndroidTest.xml b/apex/statsd/framework/test/AndroidTest.xml deleted file mode 100644 index fb519150ecd5..000000000000 --- a/apex/statsd/framework/test/AndroidTest.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2020 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<configuration description="Runs Tests for Statsd."> - <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> - <option name="test-file-name" value="FrameworkStatsdTest.apk" /> - <option name="install-arg" value="-g" /> - </target_preparer> - - <option name="test-suite-tag" value="apct" /> - <option name="test-suite-tag" value="mts" /> - <option name="test-tag" value="FrameworkStatsdTest" /> - <test class="com.android.tradefed.testtype.AndroidJUnitTest" > - <option name="package" value="com.android.os.statsd.framework.test" /> - <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> - <option name="hidden-api-checks" value="false"/> - </test> - - <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.google.android.os.statsd" /> - </object> -</configuration>
\ No newline at end of file diff --git a/apex/statsd/framework/test/src/android/app/PullAtomMetadataTest.java b/apex/statsd/framework/test/src/android/app/PullAtomMetadataTest.java deleted file mode 100644 index fd386bd8e32e..000000000000 --- a/apex/statsd/framework/test/src/android/app/PullAtomMetadataTest.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.app; - -import static com.google.common.truth.Truth.assertThat; - -import android.app.StatsManager.PullAtomMetadata; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -@SmallTest -@RunWith(AndroidJUnit4.class) -public final class PullAtomMetadataTest { - - @Test - public void testEmpty() { - PullAtomMetadata metadata = new PullAtomMetadata.Builder().build(); - assertThat(metadata.getTimeoutMillis()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_MILLIS); - assertThat(metadata.getCoolDownMillis()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_MILLIS); - assertThat(metadata.getAdditiveFields()).isNull(); - } - - @Test - public void testSetTimeoutMillis() { - long timeoutMillis = 500L; - PullAtomMetadata metadata = - new PullAtomMetadata.Builder().setTimeoutMillis(timeoutMillis).build(); - assertThat(metadata.getTimeoutMillis()).isEqualTo(timeoutMillis); - assertThat(metadata.getCoolDownMillis()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_MILLIS); - assertThat(metadata.getAdditiveFields()).isNull(); - } - - @Test - public void testSetCoolDownMillis() { - long coolDownMillis = 10_000L; - PullAtomMetadata metadata = - new PullAtomMetadata.Builder().setCoolDownMillis(coolDownMillis).build(); - assertThat(metadata.getTimeoutMillis()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_MILLIS); - assertThat(metadata.getCoolDownMillis()).isEqualTo(coolDownMillis); - assertThat(metadata.getAdditiveFields()).isNull(); - } - - @Test - public void testSetAdditiveFields() { - int[] fields = {2, 4, 6}; - PullAtomMetadata metadata = - new PullAtomMetadata.Builder().setAdditiveFields(fields).build(); - assertThat(metadata.getTimeoutMillis()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_MILLIS); - assertThat(metadata.getCoolDownMillis()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_MILLIS); - assertThat(metadata.getAdditiveFields()).isEqualTo(fields); - } - - @Test - public void testSetAllElements() { - long timeoutMillis = 300L; - long coolDownMillis = 9572L; - int[] fields = {3, 2}; - PullAtomMetadata metadata = new PullAtomMetadata.Builder() - .setTimeoutMillis(timeoutMillis) - .setCoolDownMillis(coolDownMillis) - .setAdditiveFields(fields) - .build(); - assertThat(metadata.getTimeoutMillis()).isEqualTo(timeoutMillis); - assertThat(metadata.getCoolDownMillis()).isEqualTo(coolDownMillis); - assertThat(metadata.getAdditiveFields()).isEqualTo(fields); - } -} diff --git a/apex/statsd/framework/test/src/android/os/StatsDimensionsValueTest.java b/apex/statsd/framework/test/src/android/os/StatsDimensionsValueTest.java deleted file mode 100644 index db25911e6eee..000000000000 --- a/apex/statsd/framework/test/src/android/os/StatsDimensionsValueTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.os; - -import static com.google.common.truth.Truth.assertThat; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -import java.util.List; - -@RunWith(JUnit4.class) -public final class StatsDimensionsValueTest { - - @Test - public void testConversionFromStructuredParcel() { - int tupleField = 100; // atom id - String stringValue = "Hello"; - int intValue = 123; - long longValue = 123456789L; - float floatValue = 1.1f; - boolean boolValue = true; - - // Construct structured parcel - StatsDimensionsValueParcel sdvp = new StatsDimensionsValueParcel(); - sdvp.field = tupleField; - sdvp.valueType = StatsDimensionsValue.TUPLE_VALUE_TYPE; - sdvp.tupleValue = new StatsDimensionsValueParcel[5]; - - for (int i = 0; i < 5; i++) { - sdvp.tupleValue[i] = new StatsDimensionsValueParcel(); - sdvp.tupleValue[i].field = i + 1; - } - - sdvp.tupleValue[0].valueType = StatsDimensionsValue.STRING_VALUE_TYPE; - sdvp.tupleValue[1].valueType = StatsDimensionsValue.INT_VALUE_TYPE; - sdvp.tupleValue[2].valueType = StatsDimensionsValue.LONG_VALUE_TYPE; - sdvp.tupleValue[3].valueType = StatsDimensionsValue.FLOAT_VALUE_TYPE; - sdvp.tupleValue[4].valueType = StatsDimensionsValue.BOOLEAN_VALUE_TYPE; - - sdvp.tupleValue[0].stringValue = stringValue; - sdvp.tupleValue[1].intValue = intValue; - sdvp.tupleValue[2].longValue = longValue; - sdvp.tupleValue[3].floatValue = floatValue; - sdvp.tupleValue[4].boolValue = boolValue; - - // Convert to StatsDimensionsValue and check result - StatsDimensionsValue sdv = new StatsDimensionsValue(sdvp); - - assertThat(sdv.getField()).isEqualTo(tupleField); - assertThat(sdv.getValueType()).isEqualTo(StatsDimensionsValue.TUPLE_VALUE_TYPE); - List<StatsDimensionsValue> sdvChildren = sdv.getTupleValueList(); - assertThat(sdvChildren.size()).isEqualTo(5); - - for (int i = 0; i < 5; i++) { - assertThat(sdvChildren.get(i).getField()).isEqualTo(i + 1); - } - - assertThat(sdvChildren.get(0).getValueType()) - .isEqualTo(StatsDimensionsValue.STRING_VALUE_TYPE); - assertThat(sdvChildren.get(1).getValueType()) - .isEqualTo(StatsDimensionsValue.INT_VALUE_TYPE); - assertThat(sdvChildren.get(2).getValueType()) - .isEqualTo(StatsDimensionsValue.LONG_VALUE_TYPE); - assertThat(sdvChildren.get(3).getValueType()) - .isEqualTo(StatsDimensionsValue.FLOAT_VALUE_TYPE); - assertThat(sdvChildren.get(4).getValueType()) - .isEqualTo(StatsDimensionsValue.BOOLEAN_VALUE_TYPE); - - assertThat(sdvChildren.get(0).getStringValue()).isEqualTo(stringValue); - assertThat(sdvChildren.get(1).getIntValue()).isEqualTo(intValue); - assertThat(sdvChildren.get(2).getLongValue()).isEqualTo(longValue); - assertThat(sdvChildren.get(3).getFloatValue()).isEqualTo(floatValue); - assertThat(sdvChildren.get(4).getBooleanValue()).isEqualTo(boolValue); - - // Ensure that StatsDimensionsValue and StatsDimensionsValueParcel are - // parceled equivalently - Parcel sdvpParcel = Parcel.obtain(); - Parcel sdvParcel = Parcel.obtain(); - sdvp.writeToParcel(sdvpParcel, 0); - sdv.writeToParcel(sdvParcel, 0); - assertThat(sdvpParcel.dataSize()).isEqualTo(sdvParcel.dataSize()); - } - - @Test - public void testNullTupleArray() { - int tupleField = 100; // atom id - - StatsDimensionsValueParcel parcel = new StatsDimensionsValueParcel(); - parcel.field = tupleField; - parcel.valueType = StatsDimensionsValue.TUPLE_VALUE_TYPE; - parcel.tupleValue = null; - - StatsDimensionsValue sdv = new StatsDimensionsValue(parcel); - assertThat(sdv.getField()).isEqualTo(tupleField); - assertThat(sdv.getValueType()).isEqualTo(StatsDimensionsValue.TUPLE_VALUE_TYPE); - List<StatsDimensionsValue> sdvChildren = sdv.getTupleValueList(); - assertThat(sdvChildren.size()).isEqualTo(0); - } -} diff --git a/apex/statsd/framework/test/src/android/util/StatsEventTest.java b/apex/statsd/framework/test/src/android/util/StatsEventTest.java deleted file mode 100644 index 8d263699d9c8..000000000000 --- a/apex/statsd/framework/test/src/android/util/StatsEventTest.java +++ /dev/null @@ -1,818 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.util; - -import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; - -import static java.nio.charset.StandardCharsets.UTF_8; - -import android.os.SystemClock; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.google.common.collect.Range; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Random; - -/** - * Internal tests for {@link StatsEvent}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class StatsEventTest { - - @Test - public void testNoFields() { - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder().usePooledBuffer().build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - final int expectedAtomId = 0; - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(3); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("Third element is not errors type") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ERRORS); - - final int errorMask = buffer.getInt(); - - assertWithMessage("ERROR_NO_ATOM_ID should be the only error in the error mask") - .that(errorMask).isEqualTo(StatsEvent.ERROR_NO_ATOM_ID); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testOnlyAtomId() { - final int expectedAtomId = 109; - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .setAtomId(expectedAtomId) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(2); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testIntBooleanIntInt() { - final int expectedAtomId = 109; - final int field1 = 1; - final boolean field2 = true; - final int field3 = 3; - final int field4 = 4; - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .setAtomId(expectedAtomId) - .writeInt(field1) - .writeBoolean(field2) - .writeInt(field3) - .writeInt(field4) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(6); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("First field is not Int") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect field 1") - .that(buffer.getInt()).isEqualTo(field1); - - assertWithMessage("Second field is not Boolean") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN); - - assertWithMessage("Incorrect field 2") - .that(buffer.get()).isEqualTo(1); - - assertWithMessage("Third field is not Int") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect field 3") - .that(buffer.getInt()).isEqualTo(field3); - - assertWithMessage("Fourth field is not Int") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect field 4") - .that(buffer.getInt()).isEqualTo(field4); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testStringFloatByteArray() { - final int expectedAtomId = 109; - final String field1 = "Str 1"; - final float field2 = 9.334f; - final byte[] field3 = new byte[] { 56, 23, 89, -120 }; - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .setAtomId(expectedAtomId) - .writeString(field1) - .writeFloat(field2) - .writeByteArray(field3) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(5); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("First field is not String") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_STRING); - - final String field1Actual = getStringFromByteBuffer(buffer); - assertWithMessage("Incorrect field 1") - .that(field1Actual).isEqualTo(field1); - - assertWithMessage("Second field is not Float") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_FLOAT); - - assertWithMessage("Incorrect field 2") - .that(buffer.getFloat()).isEqualTo(field2); - - assertWithMessage("Third field is not byte array") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BYTE_ARRAY); - - final byte[] field3Actual = getByteArrayFromByteBuffer(buffer); - assertWithMessage("Incorrect field 3") - .that(field3Actual).isEqualTo(field3); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testAttributionChainLong() { - final int expectedAtomId = 109; - final int[] uids = new int[] { 1, 2, 3, 4, 5 }; - final String[] tags = new String[] { "1", "2", "3", "4", "5" }; - final long field2 = -230909823L; - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .setAtomId(expectedAtomId) - .writeAttributionChain(uids, tags) - .writeLong(field2) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(4); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("First field is not Attribution Chain") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ATTRIBUTION_CHAIN); - - assertWithMessage("Incorrect number of attribution nodes") - .that(buffer.get()).isEqualTo((byte) uids.length); - - for (int i = 0; i < tags.length; i++) { - assertWithMessage("Incorrect uid in Attribution Chain") - .that(buffer.getInt()).isEqualTo(uids[i]); - - final String tag = getStringFromByteBuffer(buffer); - assertWithMessage("Incorrect tag in Attribution Chain") - .that(tag).isEqualTo(tags[i]); - } - - assertWithMessage("Second field is not Long") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect field 2") - .that(buffer.getLong()).isEqualTo(field2); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testKeyValuePairs() { - final int expectedAtomId = 109; - final SparseIntArray intMap = new SparseIntArray(); - final SparseLongArray longMap = new SparseLongArray(); - final SparseArray<String> stringMap = new SparseArray<>(); - final SparseArray<Float> floatMap = new SparseArray<>(); - intMap.put(1, -1); - intMap.put(2, -2); - stringMap.put(3, "abc"); - stringMap.put(4, "2h"); - floatMap.put(9, -234.344f); - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .setAtomId(expectedAtomId) - .writeKeyValuePairs(intMap, longMap, stringMap, floatMap) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(3); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("First field is not KeyValuePairs") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_KEY_VALUE_PAIRS); - - assertWithMessage("Incorrect number of key value pairs") - .that(buffer.get()).isEqualTo( - (byte) (intMap.size() + longMap.size() + stringMap.size() - + floatMap.size())); - - for (int i = 0; i < intMap.size(); i++) { - assertWithMessage("Incorrect key in intMap") - .that(buffer.getInt()).isEqualTo(intMap.keyAt(i)); - assertWithMessage("The type id of the value should be TYPE_INT in intMap") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - assertWithMessage("Incorrect value in intMap") - .that(buffer.getInt()).isEqualTo(intMap.valueAt(i)); - } - - for (int i = 0; i < longMap.size(); i++) { - assertWithMessage("Incorrect key in longMap") - .that(buffer.getInt()).isEqualTo(longMap.keyAt(i)); - assertWithMessage("The type id of the value should be TYPE_LONG in longMap") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - assertWithMessage("Incorrect value in longMap") - .that(buffer.getLong()).isEqualTo(longMap.valueAt(i)); - } - - for (int i = 0; i < stringMap.size(); i++) { - assertWithMessage("Incorrect key in stringMap") - .that(buffer.getInt()).isEqualTo(stringMap.keyAt(i)); - assertWithMessage("The type id of the value should be TYPE_STRING in stringMap") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_STRING); - final String value = getStringFromByteBuffer(buffer); - assertWithMessage("Incorrect value in stringMap") - .that(value).isEqualTo(stringMap.valueAt(i)); - } - - for (int i = 0; i < floatMap.size(); i++) { - assertWithMessage("Incorrect key in floatMap") - .that(buffer.getInt()).isEqualTo(floatMap.keyAt(i)); - assertWithMessage("The type id of the value should be TYPE_FLOAT in floatMap") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_FLOAT); - assertWithMessage("Incorrect value in floatMap") - .that(buffer.getFloat()).isEqualTo(floatMap.valueAt(i)); - } - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testSingleAnnotations() { - final int expectedAtomId = 109; - final int field1 = 1; - final byte field1AnnotationId = 45; - final boolean field1AnnotationValue = false; - final boolean field2 = true; - final byte field2AnnotationId = 1; - final int field2AnnotationValue = 23; - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .setAtomId(expectedAtomId) - .writeInt(field1) - .addBooleanAnnotation(field1AnnotationId, field1AnnotationValue) - .writeBoolean(field2) - .addIntAnnotation(field2AnnotationId, field2AnnotationValue) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(4); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - - final byte field1Header = buffer.get(); - final int field1AnnotationValueCount = field1Header >> 4; - final byte field1Type = (byte) (field1Header & 0x0F); - assertWithMessage("First field is not Int") - .that(field1Type).isEqualTo(StatsEvent.TYPE_INT); - assertWithMessage("First field annotation count is wrong") - .that(field1AnnotationValueCount).isEqualTo(1); - assertWithMessage("Incorrect field 1") - .that(buffer.getInt()).isEqualTo(field1); - assertWithMessage("First field's annotation id is wrong") - .that(buffer.get()).isEqualTo(field1AnnotationId); - assertWithMessage("First field's annotation type is wrong") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN); - assertWithMessage("First field's annotation value is wrong") - .that(buffer.get()).isEqualTo(field1AnnotationValue ? 1 : 0); - - final byte field2Header = buffer.get(); - final int field2AnnotationValueCount = field2Header >> 4; - final byte field2Type = (byte) (field2Header & 0x0F); - assertWithMessage("Second field is not boolean") - .that(field2Type).isEqualTo(StatsEvent.TYPE_BOOLEAN); - assertWithMessage("Second field annotation count is wrong") - .that(field2AnnotationValueCount).isEqualTo(1); - assertWithMessage("Incorrect field 2") - .that(buffer.get()).isEqualTo(field2 ? 1 : 0); - assertWithMessage("Second field's annotation id is wrong") - .that(buffer.get()).isEqualTo(field2AnnotationId); - assertWithMessage("Second field's annotation type is wrong") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - assertWithMessage("Second field's annotation value is wrong") - .that(buffer.getInt()).isEqualTo(field2AnnotationValue); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testAtomIdAnnotations() { - final int expectedAtomId = 109; - final byte atomAnnotationId = 84; - final int atomAnnotationValue = 9; - final int field1 = 1; - final byte field1AnnotationId = 45; - final boolean field1AnnotationValue = false; - final boolean field2 = true; - final byte field2AnnotationId = 1; - final int field2AnnotationValue = 23; - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .setAtomId(expectedAtomId) - .addIntAnnotation(atomAnnotationId, atomAnnotationValue) - .writeInt(field1) - .addBooleanAnnotation(field1AnnotationId, field1AnnotationValue) - .writeBoolean(field2) - .addIntAnnotation(field2AnnotationId, field2AnnotationValue) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(4); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - final byte atomIdHeader = buffer.get(); - final int atomIdAnnotationValueCount = atomIdHeader >> 4; - final byte atomIdValueType = (byte) (atomIdHeader & 0x0F); - assertWithMessage("Second element is not atom id") - .that(atomIdValueType).isEqualTo(StatsEvent.TYPE_INT); - assertWithMessage("Atom id annotation count is wrong") - .that(atomIdAnnotationValueCount).isEqualTo(1); - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - assertWithMessage("Atom id's annotation id is wrong") - .that(buffer.get()).isEqualTo(atomAnnotationId); - assertWithMessage("Atom id's annotation type is wrong") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - assertWithMessage("Atom id's annotation value is wrong") - .that(buffer.getInt()).isEqualTo(atomAnnotationValue); - - final byte field1Header = buffer.get(); - final int field1AnnotationValueCount = field1Header >> 4; - final byte field1Type = (byte) (field1Header & 0x0F); - assertWithMessage("First field is not Int") - .that(field1Type).isEqualTo(StatsEvent.TYPE_INT); - assertWithMessage("First field annotation count is wrong") - .that(field1AnnotationValueCount).isEqualTo(1); - assertWithMessage("Incorrect field 1") - .that(buffer.getInt()).isEqualTo(field1); - assertWithMessage("First field's annotation id is wrong") - .that(buffer.get()).isEqualTo(field1AnnotationId); - assertWithMessage("First field's annotation type is wrong") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN); - assertWithMessage("First field's annotation value is wrong") - .that(buffer.get()).isEqualTo(field1AnnotationValue ? 1 : 0); - - final byte field2Header = buffer.get(); - final int field2AnnotationValueCount = field2Header >> 4; - final byte field2Type = (byte) (field2Header & 0x0F); - assertWithMessage("Second field is not boolean") - .that(field2Type).isEqualTo(StatsEvent.TYPE_BOOLEAN); - assertWithMessage("Second field annotation count is wrong") - .that(field2AnnotationValueCount).isEqualTo(1); - assertWithMessage("Incorrect field 2") - .that(buffer.get()).isEqualTo(field2 ? 1 : 0); - assertWithMessage("Second field's annotation id is wrong") - .that(buffer.get()).isEqualTo(field2AnnotationId); - assertWithMessage("Second field's annotation type is wrong") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - assertWithMessage("Second field's annotation value is wrong") - .that(buffer.getInt()).isEqualTo(field2AnnotationValue); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testSetAtomIdNotCalledImmediately() { - final int expectedAtomId = 109; - final int field1 = 25; - final boolean field2 = true; - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .writeInt(field1) - .setAtomId(expectedAtomId) - .writeBoolean(field2) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(3); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("Third element is not errors type") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ERRORS); - - final int errorMask = buffer.getInt(); - - assertWithMessage("ERROR_ATOM_ID_INVALID_POSITION should be the only error in the mask") - .that(errorMask).isEqualTo(StatsEvent.ERROR_ATOM_ID_INVALID_POSITION); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testLargePulledEvent() { - final int expectedAtomId = 10_020; - byte[] field1 = new byte[10 * 1024]; - new Random().nextBytes(field1); - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = - StatsEvent.newBuilder().setAtomId(expectedAtomId).writeByteArray(field1).build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()) - .isEqualTo(3); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()) - .isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id").that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("Third element is not byte array") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_BYTE_ARRAY); - - final byte[] field1Actual = getByteArrayFromByteBuffer(buffer); - assertWithMessage("Incorrect field 1").that(field1Actual).isEqualTo(field1); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testPulledEventOverflow() { - final int expectedAtomId = 10_020; - byte[] field1 = new byte[50 * 1024]; - new Random().nextBytes(field1); - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = - StatsEvent.newBuilder().setAtomId(expectedAtomId).writeByteArray(field1).build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()) - .isEqualTo(3); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()) - .isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id").that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("Third element is not errors type") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_ERRORS); - - final int errorMask = buffer.getInt(); - - assertWithMessage("ERROR_OVERFLOW should be the only error in the error mask") - .that(errorMask) - .isEqualTo(StatsEvent.ERROR_OVERFLOW); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testPushedEventOverflow() { - final int expectedAtomId = 10_020; - byte[] field1 = new byte[10 * 1024]; - new Random().nextBytes(field1); - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .setAtomId(expectedAtomId) - .writeByteArray(field1) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()) - .isEqualTo(3); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()) - .isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id").that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("Third element is not errors type") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_ERRORS); - - final int errorMask = buffer.getInt(); - - assertWithMessage("ERROR_OVERFLOW should be the only error in the error mask") - .that(errorMask) - .isEqualTo(StatsEvent.ERROR_OVERFLOW); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - private static byte[] getByteArrayFromByteBuffer(final ByteBuffer buffer) { - final int numBytes = buffer.getInt(); - byte[] bytes = new byte[numBytes]; - buffer.get(bytes); - return bytes; - } - - private static String getStringFromByteBuffer(final ByteBuffer buffer) { - final byte[] bytes = getByteArrayFromByteBuffer(buffer); - return new String(bytes, UTF_8); - } -} diff --git a/apex/statsd/jni/android_util_StatsLog.cpp b/apex/statsd/jni/android_util_StatsLog.cpp deleted file mode 100644 index 71ce94923c8d..000000000000 --- a/apex/statsd/jni/android_util_StatsLog.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_NAMESPACE "StatsLog.tag." -#define LOG_TAG "StatsLog_println" - -#include <jni.h> -#include <log/log.h> -#include <nativehelper/scoped_local_ref.h> -#include "stats_buffer_writer.h" - -namespace android { - -static void android_util_StatsLog_write(JNIEnv* env, jobject clazz, jbyteArray buf, jint size, - jint atomId) { - if (buf == NULL) { - return; - } - jint actualSize = env->GetArrayLength(buf); - if (actualSize < size) { - return; - } - - jbyte* bufferArray = env->GetByteArrayElements(buf, NULL); - if (bufferArray == NULL) { - return; - } - - write_buffer_to_statsd((void*) bufferArray, size, atomId); - - env->ReleaseByteArrayElements(buf, bufferArray, 0); -} - -/* - * JNI registration. - */ -static const JNINativeMethod gMethods[] = { - /* name, signature, funcPtr */ - { "writeImpl", "([BII)V", (void*) android_util_StatsLog_write }, -}; - -int register_android_util_StatsLog(JNIEnv* env) -{ - static const char* kStatsLogClass = "android/util/StatsLog"; - - ScopedLocalRef<jclass> cls(env, env->FindClass(kStatsLogClass)); - if (cls.get() == nullptr) { - ALOGE("jni statsd registration failure, class not found '%s'", kStatsLogClass); - return JNI_ERR; - } - - const jint count = sizeof(gMethods) / sizeof(gMethods[0]); - int status = env->RegisterNatives(cls.get(), gMethods, count); - if (status < 0) { - ALOGE("jni statsd registration failure, status: %d", status); - return JNI_ERR; - } - return JNI_VERSION_1_4; -} - -}; // namespace android - -/* - * JNI Initialization - */ -jint JNI_OnLoad(JavaVM* jvm, void* reserved) { - JNIEnv* e; - - ALOGV("statsd : loading JNI\n"); - // Check JNI version - if (jvm->GetEnv((void**)&e, JNI_VERSION_1_4)) { - ALOGE("JNI version mismatch error"); - return JNI_ERR; - } - - return android::register_android_util_StatsLog(e); -} diff --git a/apex/statsd/service/Android.bp b/apex/statsd/service/Android.bp deleted file mode 100644 index df0ccfc54d64..000000000000 --- a/apex/statsd/service/Android.bp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2020 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -filegroup { - name: "service-statsd-sources", - srcs: [ - "java/**/*.java", - ], -} - -java_library { - name: "service-statsd", - srcs: [ ":service-statsd-sources" ], - sdk_version: "system_server_current", - libs: [ - "framework-annotations-lib", - "framework-statsd", - ], - plugins: ["java_api_finder"], - apex_available: [ - "com.android.os.statsd", - "test_com.android.os.statsd", - ], -} diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java deleted file mode 100644 index dc477a5590ea..000000000000 --- a/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.stats; - -import android.app.PendingIntent; -import android.app.StatsManager; -import android.content.Context; -import android.content.Intent; -import android.os.Binder; -import android.os.IPendingIntentRef; -import android.os.Process; -import android.os.StatsDimensionsValue; -import android.os.StatsDimensionsValueParcel; -import android.util.Log; - -import com.android.server.SystemService; - -import java.util.ArrayList; -import java.util.Arrays; - -/** - * @hide - */ -public class StatsCompanion { - private static final String TAG = "StatsCompanion"; - private static final boolean DEBUG = false; - - private static final int AID_STATSD = 1066; - - private static final String STATS_COMPANION_SERVICE = "statscompanion"; - private static final String STATS_MANAGER_SERVICE = "statsmanager"; - - static void enforceStatsdCallingUid() { - if (Binder.getCallingPid() == Process.myPid()) { - return; - } - if (Binder.getCallingUid() != AID_STATSD) { - throw new SecurityException("Not allowed to access StatsCompanion"); - } - } - - /** - * Lifecycle class for both {@link StatsCompanionService} and {@link StatsManagerService}. - */ - public static final class Lifecycle extends SystemService { - private StatsCompanionService mStatsCompanionService; - private StatsManagerService mStatsManagerService; - - public Lifecycle(Context context) { - super(context); - } - - @Override - public void onStart() { - mStatsCompanionService = new StatsCompanionService(getContext()); - mStatsManagerService = new StatsManagerService(getContext()); - mStatsCompanionService.setStatsManagerService(mStatsManagerService); - mStatsManagerService.setStatsCompanionService(mStatsCompanionService); - - try { - publishBinderService(STATS_COMPANION_SERVICE, mStatsCompanionService); - if (DEBUG) Log.d(TAG, "Published " + STATS_COMPANION_SERVICE); - publishBinderService(STATS_MANAGER_SERVICE, mStatsManagerService); - if (DEBUG) Log.d(TAG, "Published " + STATS_MANAGER_SERVICE); - } catch (Exception e) { - Log.e(TAG, "Failed to publishBinderService", e); - } - } - - @Override - public void onBootPhase(int phase) { - super.onBootPhase(phase); - if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { - mStatsCompanionService.systemReady(); - } - if (phase == PHASE_BOOT_COMPLETED) { - mStatsCompanionService.bootCompleted(); - } - } - } - - /** - * Wrapper for {@link PendingIntent}. Allows Statsd to send PendingIntents. - */ - public static class PendingIntentRef extends IPendingIntentRef.Stub { - - private static final String TAG = "PendingIntentRef"; - - /** - * The last report time is provided with each intent registered to - * StatsManager#setFetchReportsOperation. This allows easy de-duping in the receiver if - * statsd is requesting the client to retrieve the same statsd data. The last report time - * corresponds to the last_report_elapsed_nanos that will provided in the current - * ConfigMetricsReport, and this timestamp also corresponds to the - * current_report_elapsed_nanos of the most recently obtained ConfigMetricsReport. - */ - private static final String EXTRA_LAST_REPORT_TIME = "android.app.extra.LAST_REPORT_TIME"; - private static final int CODE_DATA_BROADCAST = 1; - private static final int CODE_ACTIVE_CONFIGS_BROADCAST = 1; - private static final int CODE_SUBSCRIBER_BROADCAST = 1; - - private final PendingIntent mPendingIntent; - private final Context mContext; - - public PendingIntentRef(PendingIntent pendingIntent, Context context) { - mPendingIntent = pendingIntent; - mContext = context; - } - - @Override - public void sendDataBroadcast(long lastReportTimeNs) { - enforceStatsdCallingUid(); - Intent intent = new Intent(); - intent.putExtra(EXTRA_LAST_REPORT_TIME, lastReportTimeNs); - try { - mPendingIntent.send(mContext, CODE_DATA_BROADCAST, intent, null, null); - } catch (PendingIntent.CanceledException e) { - Log.w(TAG, "Unable to send PendingIntent"); - } - } - - @Override - public void sendActiveConfigsChangedBroadcast(long[] configIds) { - enforceStatsdCallingUid(); - Intent intent = new Intent(); - intent.putExtra(StatsManager.EXTRA_STATS_ACTIVE_CONFIG_KEYS, configIds); - try { - mPendingIntent.send(mContext, CODE_ACTIVE_CONFIGS_BROADCAST, intent, null, null); - if (DEBUG) { - Log.d(TAG, "Sent broadcast with config ids " + Arrays.toString(configIds)); - } - } catch (PendingIntent.CanceledException e) { - Log.w(TAG, "Unable to send active configs changed broadcast using PendingIntent"); - } - } - - @Override - public void sendSubscriberBroadcast(long configUid, long configId, long subscriptionId, - long subscriptionRuleId, String[] cookies, - StatsDimensionsValueParcel dimensionsValueParcel) { - enforceStatsdCallingUid(); - StatsDimensionsValue dimensionsValue = new StatsDimensionsValue(dimensionsValueParcel); - Intent intent = - new Intent() - .putExtra(StatsManager.EXTRA_STATS_CONFIG_UID, configUid) - .putExtra(StatsManager.EXTRA_STATS_CONFIG_KEY, configId) - .putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_ID, subscriptionId) - .putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_RULE_ID, - subscriptionRuleId) - .putExtra(StatsManager.EXTRA_STATS_DIMENSIONS_VALUE, dimensionsValue); - - ArrayList<String> cookieList = new ArrayList<>(cookies.length); - cookieList.addAll(Arrays.asList(cookies)); - intent.putStringArrayListExtra( - StatsManager.EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES, cookieList); - - if (DEBUG) { - Log.d(TAG, - String.format( - "Statsd sendSubscriberBroadcast with params {%d %d %d %d %s %s}", - configUid, configId, subscriptionId, subscriptionRuleId, - Arrays.toString(cookies), - dimensionsValue)); - } - try { - mPendingIntent.send(mContext, CODE_SUBSCRIBER_BROADCAST, intent, null, null); - } catch (PendingIntent.CanceledException e) { - Log.w(TAG, - "Unable to send using PendingIntent from uid " + configUid - + "; presumably it had been cancelled."); - } - } - } -} diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java deleted file mode 100644 index fbda86f9ce22..000000000000 --- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java +++ /dev/null @@ -1,770 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.server.stats; - -import static android.os.Process.THREAD_PRIORITY_BACKGROUND; - -import android.app.AlarmManager; -import android.app.AlarmManager.OnAlarmListener; -import android.app.StatsManager; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.os.Binder; -import android.os.Bundle; -import android.os.FileUtils; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.IStatsCompanionService; -import android.os.IStatsd; -import android.os.Looper; -import android.os.ParcelFileDescriptor; -import android.os.PowerManager; -import android.os.RemoteException; -import android.os.StatsFrameworkInitializer; -import android.os.SystemClock; -import android.os.UserHandle; -import android.os.UserManager; -import android.util.Log; -import android.util.proto.ProtoOutputStream; - -import com.android.internal.annotations.GuardedBy; - -import java.io.File; -import java.io.FileDescriptor; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Helper service for statsd (the native stats management service in cmds/statsd/). - * Used for registering and receiving alarms on behalf of statsd. - * - * @hide - */ -public class StatsCompanionService extends IStatsCompanionService.Stub { - - private static final long MILLIS_IN_A_DAY = TimeUnit.DAYS.toMillis(1); - - public static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity"; - public static final String CONFIG_DIR = "/data/misc/stats-service"; - - static final String TAG = "StatsCompanionService"; - static final boolean DEBUG = false; - /** - * Hard coded field ids of frameworks/base/cmds/statsd/src/uid_data.proto - * to be used in ProtoOutputStream. - */ - private static final int APPLICATION_INFO_FIELD_ID = 1; - private static final int UID_FIELD_ID = 1; - private static final int VERSION_FIELD_ID = 2; - private static final int VERSION_STRING_FIELD_ID = 3; - private static final int PACKAGE_NAME_FIELD_ID = 4; - private static final int INSTALLER_FIELD_ID = 5; - - public static final int DEATH_THRESHOLD = 10; - - static final class CompanionHandler extends Handler { - CompanionHandler(Looper looper) { - super(looper); - } - } - - private final Context mContext; - private final AlarmManager mAlarmManager; - @GuardedBy("sStatsdLock") - private static IStatsd sStatsd; - private static final Object sStatsdLock = new Object(); - - private final OnAlarmListener mPullingAlarmListener; - private final OnAlarmListener mPeriodicAlarmListener; - - private StatsManagerService mStatsManagerService; - - @GuardedBy("sStatsdLock") - private final HashSet<Long> mDeathTimeMillis = new HashSet<>(); - @GuardedBy("sStatsdLock") - private final HashMap<Long, String> mDeletedFiles = new HashMap<>(); - private final CompanionHandler mHandler; - - // Flag that is set when PHASE_BOOT_COMPLETED is triggered in the StatsCompanion lifecycle. - private AtomicBoolean mBootCompleted = new AtomicBoolean(false); - - public StatsCompanionService(Context context) { - super(); - mContext = context; - mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); - if (DEBUG) Log.d(TAG, "Registered receiver for ACTION_PACKAGE_REPLACED and ADDED."); - HandlerThread handlerThread = new HandlerThread(TAG); - handlerThread.start(); - mHandler = new CompanionHandler(handlerThread.getLooper()); - - mPullingAlarmListener = new PullingAlarmListener(context); - mPeriodicAlarmListener = new PeriodicAlarmListener(context); - } - - private final static int[] toIntArray(List<Integer> list) { - int[] ret = new int[list.size()]; - for (int i = 0; i < ret.length; i++) { - ret[i] = list.get(i); - } - return ret; - } - - private final static long[] toLongArray(List<Long> list) { - long[] ret = new long[list.size()]; - for (int i = 0; i < ret.length; i++) { - ret[i] = list.get(i); - } - return ret; - } - - /** - * Non-blocking call to retrieve a reference to statsd - * - * @return IStatsd object if statsd is ready, null otherwise. - */ - private static IStatsd getStatsdNonblocking() { - synchronized (sStatsdLock) { - return sStatsd; - } - } - - private static void informAllUids(Context context) { - ParcelFileDescriptor[] fds; - try { - fds = ParcelFileDescriptor.createPipe(); - } catch (IOException e) { - Log.e(TAG, "Failed to create a pipe to send uid map data.", e); - return; - } - HandlerThread backgroundThread = new HandlerThread( - "statsCompanionService.bg", THREAD_PRIORITY_BACKGROUND); - backgroundThread.start(); - Handler handler = new Handler(backgroundThread.getLooper()); - handler.post(() -> { - UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); - PackageManager pm = context.getPackageManager(); - final List<UserHandle> users = um.getUserHandles(true); - if (DEBUG) { - Log.d(TAG, "Iterating over " + users.size() + " userHandles."); - } - IStatsd statsd = getStatsdNonblocking(); - if (statsd == null) { - return; - } - try { - statsd.informAllUidData(fds[0]); - } catch (RemoteException e) { - Log.e(TAG, "Failed to send uid map to statsd"); - } - try { - fds[0].close(); - } catch (IOException e) { - Log.e(TAG, "Failed to close the read side of the pipe.", e); - } - final ParcelFileDescriptor writeFd = fds[1]; - FileOutputStream fout = new ParcelFileDescriptor.AutoCloseOutputStream(writeFd); - try { - ProtoOutputStream output = new ProtoOutputStream(fout); - int numRecords = 0; - // Add in all the apps for every user/profile. - for (UserHandle userHandle : users) { - List<PackageInfo> packagesPlusApex = getAllPackagesWithApex(pm, userHandle); - for (int j = 0; j < packagesPlusApex.size(); j++) { - if (packagesPlusApex.get(j).applicationInfo != null) { - String installer; - try { - installer = pm.getInstallerPackageName( - packagesPlusApex.get(j).packageName); - } catch (IllegalArgumentException e) { - installer = ""; - } - long applicationInfoToken = - output.start(ProtoOutputStream.FIELD_TYPE_MESSAGE - | ProtoOutputStream.FIELD_COUNT_REPEATED - | APPLICATION_INFO_FIELD_ID); - output.write(ProtoOutputStream.FIELD_TYPE_INT32 - | ProtoOutputStream.FIELD_COUNT_SINGLE | UID_FIELD_ID, - packagesPlusApex.get(j).applicationInfo.uid); - output.write(ProtoOutputStream.FIELD_TYPE_INT64 - | ProtoOutputStream.FIELD_COUNT_SINGLE - | VERSION_FIELD_ID, - packagesPlusApex.get(j).getLongVersionCode()); - output.write(ProtoOutputStream.FIELD_TYPE_STRING - | ProtoOutputStream.FIELD_COUNT_SINGLE - | VERSION_STRING_FIELD_ID, - packagesPlusApex.get(j).versionName); - output.write(ProtoOutputStream.FIELD_TYPE_STRING - | ProtoOutputStream.FIELD_COUNT_SINGLE - | PACKAGE_NAME_FIELD_ID, packagesPlusApex.get(j).packageName); - output.write(ProtoOutputStream.FIELD_TYPE_STRING - | ProtoOutputStream.FIELD_COUNT_SINGLE - | INSTALLER_FIELD_ID, - installer == null ? "" : installer); - numRecords++; - output.end(applicationInfoToken); - } - } - } - output.flush(); - if (DEBUG) { - Log.d(TAG, "Sent data for " + numRecords + " apps"); - } - } finally { - FileUtils.closeQuietly(fout); - backgroundThread.quit(); - backgroundThread.interrupt(); - } - }); - } - - private static List<PackageInfo> getAllPackagesWithApex(PackageManager pm, - UserHandle userHandle) { - // We want all the uninstalled packages because uninstalled package uids can still be logged - // to statsd. - List<PackageInfo> allPackages = new ArrayList<>( - pm.getInstalledPackagesAsUser(PackageManager.MATCH_UNINSTALLED_PACKAGES - | PackageManager.MATCH_ANY_USER, - userHandle.getIdentifier())); - // We make a second query to package manager for the apex modules because package manager - // returns both installed and uninstalled apexes with - // PackageManager.MATCH_UNINSTALLED_PACKAGES flag. We only want active apexes because - // inactive apexes can conflict with active ones. - for (PackageInfo packageInfo : pm.getInstalledPackages(PackageManager.MATCH_APEX)) { - if (packageInfo.isApex) { - allPackages.add(packageInfo); - } - } - return allPackages; - } - - private static class WakelockThread extends Thread { - private final PowerManager.WakeLock mWl; - private final Runnable mRunnable; - - WakelockThread(Context context, String wakelockName, Runnable runnable) { - PowerManager powerManager = (PowerManager) - context.getSystemService(Context.POWER_SERVICE); - mWl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakelockName); - mRunnable = runnable; - } - @Override - public void run() { - try { - mRunnable.run(); - } finally { - mWl.release(); - } - } - @Override - public void start() { - mWl.acquire(); - super.start(); - } - } - - private final static class AppUpdateReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - /** - * App updates actually consist of REMOVE, ADD, and then REPLACE broadcasts. To avoid - * waste, we ignore the REMOVE and ADD broadcasts that contain the replacing flag. - * If we can't find the value for EXTRA_REPLACING, we default to false. - */ - if (!intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED) - && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { - return; // Keep only replacing or normal add and remove. - } - if (DEBUG) Log.d(TAG, "StatsCompanionService noticed an app was updated."); - synchronized (sStatsdLock) { - if (sStatsd == null) { - Log.w(TAG, "Could not access statsd to inform it of an app update"); - return; - } - try { - if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) { - Bundle b = intent.getExtras(); - int uid = b.getInt(Intent.EXTRA_UID); - boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); - if (!replacing) { - // Don't bother sending an update if we're right about to get another - // intent for the new version that's added. - String app = intent.getData().getSchemeSpecificPart(); - sStatsd.informOnePackageRemoved(app, uid); - } - } else { - PackageManager pm = context.getPackageManager(); - Bundle b = intent.getExtras(); - int uid = b.getInt(Intent.EXTRA_UID); - String app = intent.getData().getSchemeSpecificPart(); - PackageInfo pi = pm.getPackageInfo(app, PackageManager.MATCH_ANY_USER); - String installer; - try { - installer = pm.getInstallerPackageName(app); - } catch (IllegalArgumentException e) { - installer = ""; - } - sStatsd.informOnePackage( - app, - uid, - pi.getLongVersionCode(), - pi.versionName == null ? "" : pi.versionName, - installer == null ? "" : installer); - } - } catch (Exception e) { - Log.w(TAG, "Failed to inform statsd of an app update", e); - } - } - } - } - - private static final class UserUpdateReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - // Pull the latest state of UID->app name, version mapping. - // Needed since the new user basically has a version of every app. - informAllUids(context); - } - } - - public final static class PullingAlarmListener implements OnAlarmListener { - private final Context mContext; - - PullingAlarmListener(Context context) { - mContext = context; - } - - @Override - public void onAlarm() { - if (DEBUG) { - Log.d(TAG, "Time to poll something."); - } - IStatsd statsd = getStatsdNonblocking(); - if (statsd == null) { - Log.w(TAG, "Could not access statsd to inform it of pulling alarm firing."); - return; - } - - // Wakelock needs to be retained while calling statsd. - Thread thread = new WakelockThread(mContext, - PullingAlarmListener.class.getCanonicalName(), new Runnable() { - @Override - public void run() { - try { - statsd.informPollAlarmFired(); - } catch (RemoteException e) { - Log.w(TAG, "Failed to inform statsd of pulling alarm firing.", e); - } - } - }); - thread.start(); - } - } - - public final static class PeriodicAlarmListener implements OnAlarmListener { - private final Context mContext; - - PeriodicAlarmListener(Context context) { - mContext = context; - } - - @Override - public void onAlarm() { - if (DEBUG) { - Log.d(TAG, "Time to trigger periodic alarm."); - } - IStatsd statsd = getStatsdNonblocking(); - if (statsd == null) { - Log.w(TAG, "Could not access statsd to inform it of periodic alarm firing."); - return; - } - - // Wakelock needs to be retained while calling statsd. - Thread thread = new WakelockThread(mContext, - PeriodicAlarmListener.class.getCanonicalName(), new Runnable() { - @Override - public void run() { - try { - statsd.informAlarmForSubscriberTriggeringFired(); - } catch (RemoteException e) { - Log.w(TAG, "Failed to inform statsd of periodic alarm firing.", e); - } - } - }); - thread.start(); - } - } - - public final static class ShutdownEventReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - /** - * Skip immediately if intent is not relevant to device shutdown. - */ - if (!intent.getAction().equals(Intent.ACTION_REBOOT) - && !(intent.getAction().equals(Intent.ACTION_SHUTDOWN) - && (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0)) { - return; - } - - if (DEBUG) { - Log.i(TAG, "StatsCompanionService noticed a shutdown."); - } - IStatsd statsd = getStatsdNonblocking(); - if (statsd == null) { - Log.w(TAG, "Could not access statsd to inform it of a shutdown event."); - return; - } - try { - // two way binder call - statsd.informDeviceShutdown(); - } catch (Exception e) { - Log.w(TAG, "Failed to inform statsd of a shutdown event.", e); - } - } - } - - @Override // Binder call - public void setAlarmForSubscriberTriggering(long timestampMs) { - StatsCompanion.enforceStatsdCallingUid(); - if (DEBUG) { - Log.d(TAG, - "Setting periodic alarm in about " + (timestampMs - - SystemClock.elapsedRealtime())); - } - final long callingToken = Binder.clearCallingIdentity(); - try { - // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will - // only fire when it awakens. - mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, timestampMs, TAG + ".periodic", - mPeriodicAlarmListener, mHandler); - } finally { - Binder.restoreCallingIdentity(callingToken); - } - } - - @Override // Binder call - public void cancelAlarmForSubscriberTriggering() { - StatsCompanion.enforceStatsdCallingUid(); - if (DEBUG) { - Log.d(TAG, "Cancelling periodic alarm"); - } - final long callingToken = Binder.clearCallingIdentity(); - try { - mAlarmManager.cancel(mPeriodicAlarmListener); - } finally { - Binder.restoreCallingIdentity(callingToken); - } - } - - @Override // Binder call - public void setPullingAlarm(long nextPullTimeMs) { - StatsCompanion.enforceStatsdCallingUid(); - if (DEBUG) { - Log.d(TAG, "Setting pulling alarm in about " - + (nextPullTimeMs - SystemClock.elapsedRealtime())); - } - final long callingToken = Binder.clearCallingIdentity(); - try { - // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will - // only fire when it awakens. - mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, nextPullTimeMs, TAG + ".pull", - mPullingAlarmListener, mHandler); - } finally { - Binder.restoreCallingIdentity(callingToken); - } - } - - @Override // Binder call - public void cancelPullingAlarm() { - StatsCompanion.enforceStatsdCallingUid(); - if (DEBUG) { - Log.d(TAG, "Cancelling pulling alarm"); - } - final long callingToken = Binder.clearCallingIdentity(); - try { - mAlarmManager.cancel(mPullingAlarmListener); - } finally { - Binder.restoreCallingIdentity(callingToken); - } - } - - @Override // Binder call - public void statsdReady() { - StatsCompanion.enforceStatsdCallingUid(); - if (DEBUG) { - Log.d(TAG, "learned that statsdReady"); - } - sayHiToStatsd(); // tell statsd that we're ready too and link to it - - final Intent intent = new Intent(StatsManager.ACTION_STATSD_STARTED); - // Retrieve list of broadcast receivers for this broadcast & send them directed broadcasts - // to wake them up (if they're in background). - List<ResolveInfo> resolveInfos = - mContext.getPackageManager().queryBroadcastReceiversAsUser( - intent, 0, UserHandle.SYSTEM); - if (resolveInfos == null || resolveInfos.isEmpty()) { - return; // No need to send broadcast. - } - - for (ResolveInfo resolveInfo : resolveInfos) { - Intent intentToSend = new Intent(intent); - intentToSend.setComponent(new ComponentName( - resolveInfo.activityInfo.applicationInfo.packageName, - resolveInfo.activityInfo.name)); - mContext.sendBroadcastAsUser(intentToSend, UserHandle.SYSTEM, - android.Manifest.permission.DUMP); - } - } - - @Override // Binder call - public boolean checkPermission(String permission, int pid, int uid) { - StatsCompanion.enforceStatsdCallingUid(); - return mContext.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_GRANTED; - } - - // Statsd related code - - /** - * Fetches the statsd IBinder service. This is a blocking call that always refetches statsd - * instead of returning the cached sStatsd. - * Note: This should only be called from {@link #sayHiToStatsd()}. All other clients should use - * the cached sStatsd via {@link #getStatsdNonblocking()}. - */ - private IStatsd fetchStatsdServiceLocked() { - sStatsd = IStatsd.Stub.asInterface(StatsFrameworkInitializer - .getStatsServiceManager() - .getStatsdServiceRegisterer() - .get()); - return sStatsd; - } - - private void registerStatsdDeathRecipient(IStatsd statsd, List<BroadcastReceiver> receivers) { - StatsdDeathRecipient deathRecipient = new StatsdDeathRecipient(statsd, receivers); - - try { - statsd.asBinder().linkToDeath(deathRecipient, /*flags=*/0); - } catch (RemoteException e) { - Log.e(TAG, "linkToDeath (StatsdDeathRecipient) failed"); - // Statsd has already died. Unregister receivers ourselves. - for (BroadcastReceiver receiver : receivers) { - mContext.unregisterReceiver(receiver); - } - synchronized (sStatsdLock) { - if (statsd == sStatsd) { - statsdNotReadyLocked(); - } - } - } - } - - /** - * Now that the android system is ready, StatsCompanion is ready too, so inform statsd. - */ - void systemReady() { - if (DEBUG) Log.d(TAG, "Learned that systemReady"); - sayHiToStatsd(); - } - - void setStatsManagerService(StatsManagerService statsManagerService) { - mStatsManagerService = statsManagerService; - } - - /** - * Tells statsd that statscompanion is ready. If the binder call returns, link to - * statsd. - */ - private void sayHiToStatsd() { - IStatsd statsd; - synchronized (sStatsdLock) { - if (sStatsd != null && sStatsd.asBinder().isBinderAlive()) { - Log.e(TAG, "statsd has already been fetched before", - new IllegalStateException("IStatsd object should be null or dead")); - return; - } - statsd = fetchStatsdServiceLocked(); - } - - if (statsd == null) { - Log.i(TAG, "Could not yet find statsd to tell it that StatsCompanion is alive."); - return; - } - - // Cleann up from previous statsd - cancel any alarms that had been set. Do this here - // instead of in binder death because statsd can come back and set different alarms, or not - // want to set an alarm when it had been set. This guarantees that when we get a new statsd, - // we cancel any alarms before it is able to set them. - cancelPullingAlarm(); - cancelAlarmForSubscriberTriggering(); - - if (DEBUG) Log.d(TAG, "Saying hi to statsd"); - mStatsManagerService.statsdReady(statsd); - try { - statsd.statsCompanionReady(); - - BroadcastReceiver appUpdateReceiver = new AppUpdateReceiver(); - BroadcastReceiver userUpdateReceiver = new UserUpdateReceiver(); - BroadcastReceiver shutdownEventReceiver = new ShutdownEventReceiver(); - - // Setup broadcast receiver for updates. - IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REPLACED); - filter.addAction(Intent.ACTION_PACKAGE_ADDED); - filter.addAction(Intent.ACTION_PACKAGE_REMOVED); - filter.addDataScheme("package"); - mContext.registerReceiverForAllUsers(appUpdateReceiver, filter, null, null); - - // Setup receiver for user initialize (which happens once for a new user) - // and if a user is removed. - filter = new IntentFilter(Intent.ACTION_USER_INITIALIZE); - filter.addAction(Intent.ACTION_USER_REMOVED); - mContext.registerReceiverForAllUsers(userUpdateReceiver, filter, null, null); - - // Setup receiver for device reboots or shutdowns. - filter = new IntentFilter(Intent.ACTION_REBOOT); - filter.addAction(Intent.ACTION_SHUTDOWN); - mContext.registerReceiverForAllUsers(shutdownEventReceiver, filter, null, null); - - // Register death recipient. - List<BroadcastReceiver> broadcastReceivers = - List.of(appUpdateReceiver, userUpdateReceiver, shutdownEventReceiver); - registerStatsdDeathRecipient(statsd, broadcastReceivers); - - // Tell statsd that boot has completed. The signal may have already been sent, but since - // the signal-receiving function is idempotent, that's ok. - if (mBootCompleted.get()) { - statsd.bootCompleted(); - } - - // Pull the latest state of UID->app name, version mapping when statsd starts. - informAllUids(mContext); - - Log.i(TAG, "Told statsd that StatsCompanionService is alive."); - } catch (RemoteException e) { - Log.e(TAG, "Failed to inform statsd that statscompanion is ready", e); - } - } - - private class StatsdDeathRecipient implements IBinder.DeathRecipient { - - private final IStatsd mStatsd; - private final List<BroadcastReceiver> mReceiversToUnregister; - - StatsdDeathRecipient(IStatsd statsd, List<BroadcastReceiver> receivers) { - mStatsd = statsd; - mReceiversToUnregister = receivers; - } - - // It is possible for binderDied to be called after a restarted statsd calls statsdReady, - // but that's alright because the code does not assume an ordering of the two calls. - @Override - public void binderDied() { - Log.i(TAG, "Statsd is dead - erase all my knowledge, except pullers"); - synchronized (sStatsdLock) { - long now = SystemClock.elapsedRealtime(); - for (Long timeMillis : mDeathTimeMillis) { - long ageMillis = now - timeMillis; - if (ageMillis > MILLIS_IN_A_DAY) { - mDeathTimeMillis.remove(timeMillis); - } - } - for (Long timeMillis : mDeletedFiles.keySet()) { - long ageMillis = now - timeMillis; - if (ageMillis > MILLIS_IN_A_DAY * 7) { - mDeletedFiles.remove(timeMillis); - } - } - mDeathTimeMillis.add(now); - if (mDeathTimeMillis.size() >= DEATH_THRESHOLD) { - mDeathTimeMillis.clear(); - File[] configs = new File(CONFIG_DIR).listFiles(); - if (configs != null && configs.length > 0) { - String fileName = configs[0].getName(); - if (configs[0].delete()) { - mDeletedFiles.put(now, fileName); - } - } - } - - // Unregister receivers on death because receivers can only be unregistered once. - // Otherwise, an IllegalArgumentException is thrown. - for (BroadcastReceiver receiver: mReceiversToUnregister) { - mContext.unregisterReceiver(receiver); - } - - // It's possible for statsd to have restarted and called statsdReady, causing a new - // sStatsd binder object to be fetched, before the binderDied callback runs. Only - // call #statsdNotReadyLocked if that hasn't happened yet. - if (mStatsd == sStatsd) { - statsdNotReadyLocked(); - } - } - } - } - - private void statsdNotReadyLocked() { - sStatsd = null; - mStatsManagerService.statsdNotReady(); - } - - void bootCompleted() { - mBootCompleted.set(true); - IStatsd statsd = getStatsdNonblocking(); - if (statsd == null) { - // Statsd is not yet ready. - // Delay the boot completed ping to {@link #sayHiToStatsd()} - return; - } - try { - statsd.bootCompleted(); - } catch (RemoteException e) { - Log.e(TAG, "Failed to notify statsd that boot completed"); - } - } - - @Override - protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - return; - } - - synchronized (sStatsdLock) { - writer.println("Number of configuration files deleted: " + mDeletedFiles.size()); - if (mDeletedFiles.size() > 0) { - writer.println(" timestamp, deleted file name"); - } - long lastBootMillis = - SystemClock.currentThreadTimeMillis() - SystemClock.elapsedRealtime(); - for (Long elapsedMillis : mDeletedFiles.keySet()) { - long deletionMillis = lastBootMillis + elapsedMillis; - writer.println(" " + deletionMillis + ", " + mDeletedFiles.get(elapsedMillis)); - } - } - } -} diff --git a/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java b/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java deleted file mode 100644 index 1e3846bc4a0b..000000000000 --- a/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java +++ /dev/null @@ -1,668 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.stats; - -import static com.android.server.stats.StatsCompanion.PendingIntentRef; - -import android.Manifest; -import android.annotation.Nullable; -import android.app.AppOpsManager; -import android.app.PendingIntent; -import android.content.Context; -import android.os.Binder; -import android.os.IPullAtomCallback; -import android.os.IStatsManagerService; -import android.os.IStatsd; -import android.os.PowerManager; -import android.os.Process; -import android.os.RemoteException; -import android.util.ArrayMap; -import android.util.Log; - -import com.android.internal.annotations.GuardedBy; - -import java.util.Map; -import java.util.Objects; - -/** - * Service for {@link android.app.StatsManager}. - * - * @hide - */ -public class StatsManagerService extends IStatsManagerService.Stub { - - private static final String TAG = "StatsManagerService"; - private static final boolean DEBUG = false; - - private static final int STATSD_TIMEOUT_MILLIS = 5000; - - private static final String USAGE_STATS_PERMISSION_OPS = "android:get_usage_stats"; - - @GuardedBy("mLock") - private IStatsd mStatsd; - private final Object mLock = new Object(); - - private StatsCompanionService mStatsCompanionService; - private Context mContext; - - @GuardedBy("mLock") - private ArrayMap<ConfigKey, PendingIntentRef> mDataFetchPirMap = new ArrayMap<>(); - @GuardedBy("mLock") - private ArrayMap<Integer, PendingIntentRef> mActiveConfigsPirMap = new ArrayMap<>(); - @GuardedBy("mLock") - private ArrayMap<ConfigKey, ArrayMap<Long, PendingIntentRef>> mBroadcastSubscriberPirMap = - new ArrayMap<>(); - - public StatsManagerService(Context context) { - super(); - mContext = context; - } - - private static class ConfigKey { - private final int mUid; - private final long mConfigId; - - ConfigKey(int uid, long configId) { - mUid = uid; - mConfigId = configId; - } - - public int getUid() { - return mUid; - } - - public long getConfigId() { - return mConfigId; - } - - @Override - public int hashCode() { - return Objects.hash(mUid, mConfigId); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof ConfigKey) { - ConfigKey other = (ConfigKey) obj; - return this.mUid == other.getUid() && this.mConfigId == other.getConfigId(); - } - return false; - } - } - - private static class PullerKey { - private final int mUid; - private final int mAtomTag; - - PullerKey(int uid, int atom) { - mUid = uid; - mAtomTag = atom; - } - - public int getUid() { - return mUid; - } - - public int getAtom() { - return mAtomTag; - } - - @Override - public int hashCode() { - return Objects.hash(mUid, mAtomTag); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof PullerKey) { - PullerKey other = (PullerKey) obj; - return this.mUid == other.getUid() && this.mAtomTag == other.getAtom(); - } - return false; - } - } - - private static class PullerValue { - private final long mCoolDownMillis; - private final long mTimeoutMillis; - private final int[] mAdditiveFields; - private final IPullAtomCallback mCallback; - - PullerValue(long coolDownMillis, long timeoutMillis, int[] additiveFields, - IPullAtomCallback callback) { - mCoolDownMillis = coolDownMillis; - mTimeoutMillis = timeoutMillis; - mAdditiveFields = additiveFields; - mCallback = callback; - } - - public long getCoolDownMillis() { - return mCoolDownMillis; - } - - public long getTimeoutMillis() { - return mTimeoutMillis; - } - - public int[] getAdditiveFields() { - return mAdditiveFields; - } - - public IPullAtomCallback getCallback() { - return mCallback; - } - } - - private final ArrayMap<PullerKey, PullerValue> mPullers = new ArrayMap<>(); - - @Override - public void registerPullAtomCallback(int atomTag, long coolDownMillis, long timeoutMillis, - int[] additiveFields, IPullAtomCallback pullerCallback) { - enforceRegisterStatsPullAtomPermission(); - if (pullerCallback == null) { - Log.w(TAG, "Puller callback is null for atom " + atomTag); - return; - } - int callingUid = Binder.getCallingUid(); - PullerKey key = new PullerKey(callingUid, atomTag); - PullerValue val = - new PullerValue(coolDownMillis, timeoutMillis, additiveFields, pullerCallback); - - // Always cache the puller in StatsManagerService. If statsd is down, we will register the - // puller when statsd comes back up. - synchronized (mLock) { - mPullers.put(key, val); - } - - IStatsd statsd = getStatsdNonblocking(); - if (statsd == null) { - return; - } - - final long token = Binder.clearCallingIdentity(); - try { - statsd.registerPullAtomCallback(callingUid, atomTag, coolDownMillis, timeoutMillis, - additiveFields, pullerCallback); - } catch (RemoteException e) { - Log.e(TAG, "Failed to access statsd to register puller for atom " + atomTag); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void unregisterPullAtomCallback(int atomTag) { - enforceRegisterStatsPullAtomPermission(); - int callingUid = Binder.getCallingUid(); - PullerKey key = new PullerKey(callingUid, atomTag); - - // Always remove the puller from StatsManagerService even if statsd is down. When statsd - // comes back up, we will not re-register the removed puller. - synchronized (mLock) { - mPullers.remove(key); - } - - IStatsd statsd = getStatsdNonblocking(); - if (statsd == null) { - return; - } - - final long token = Binder.clearCallingIdentity(); - try { - statsd.unregisterPullAtomCallback(callingUid, atomTag); - } catch (RemoteException e) { - Log.e(TAG, "Failed to access statsd to unregister puller for atom " + atomTag); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void setDataFetchOperation(long configId, PendingIntent pendingIntent, - String packageName) { - enforceDumpAndUsageStatsPermission(packageName); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - PendingIntentRef pir = new PendingIntentRef(pendingIntent, mContext); - ConfigKey key = new ConfigKey(callingUid, configId); - // We add the PIR to a map so we can reregister if statsd is unavailable. - synchronized (mLock) { - mDataFetchPirMap.put(key, pir); - } - try { - IStatsd statsd = getStatsdNonblocking(); - if (statsd != null) { - statsd.setDataFetchOperation(configId, pir, callingUid); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to setDataFetchOperation with statsd"); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void removeDataFetchOperation(long configId, String packageName) { - enforceDumpAndUsageStatsPermission(packageName); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - ConfigKey key = new ConfigKey(callingUid, configId); - synchronized (mLock) { - mDataFetchPirMap.remove(key); - } - try { - IStatsd statsd = getStatsdNonblocking(); - if (statsd != null) { - statsd.removeDataFetchOperation(configId, callingUid); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to removeDataFetchOperation with statsd"); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public long[] setActiveConfigsChangedOperation(PendingIntent pendingIntent, - String packageName) { - enforceDumpAndUsageStatsPermission(packageName); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - PendingIntentRef pir = new PendingIntentRef(pendingIntent, mContext); - // We add the PIR to a map so we can reregister if statsd is unavailable. - synchronized (mLock) { - mActiveConfigsPirMap.put(callingUid, pir); - } - try { - IStatsd statsd = getStatsdNonblocking(); - if (statsd != null) { - return statsd.setActiveConfigsChangedOperation(pir, callingUid); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to setActiveConfigsChangedOperation with statsd"); - } finally { - Binder.restoreCallingIdentity(token); - } - return new long[] {}; - } - - @Override - public void removeActiveConfigsChangedOperation(String packageName) { - enforceDumpAndUsageStatsPermission(packageName); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - synchronized (mLock) { - mActiveConfigsPirMap.remove(callingUid); - } - try { - IStatsd statsd = getStatsdNonblocking(); - if (statsd != null) { - statsd.removeActiveConfigsChangedOperation(callingUid); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to removeActiveConfigsChangedOperation with statsd"); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void setBroadcastSubscriber(long configId, long subscriberId, - PendingIntent pendingIntent, String packageName) { - enforceDumpAndUsageStatsPermission(packageName); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - PendingIntentRef pir = new PendingIntentRef(pendingIntent, mContext); - ConfigKey key = new ConfigKey(callingUid, configId); - // We add the PIR to a map so we can reregister if statsd is unavailable. - synchronized (mLock) { - ArrayMap<Long, PendingIntentRef> innerMap = mBroadcastSubscriberPirMap - .getOrDefault(key, new ArrayMap<>()); - innerMap.put(subscriberId, pir); - mBroadcastSubscriberPirMap.put(key, innerMap); - } - try { - IStatsd statsd = getStatsdNonblocking(); - if (statsd != null) { - statsd.setBroadcastSubscriber( - configId, subscriberId, pir, callingUid); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to setBroadcastSubscriber with statsd"); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void unsetBroadcastSubscriber(long configId, long subscriberId, String packageName) { - enforceDumpAndUsageStatsPermission(packageName); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - ConfigKey key = new ConfigKey(callingUid, configId); - synchronized (mLock) { - ArrayMap<Long, PendingIntentRef> innerMap = mBroadcastSubscriberPirMap - .getOrDefault(key, new ArrayMap<>()); - innerMap.remove(subscriberId); - if (innerMap.isEmpty()) { - mBroadcastSubscriberPirMap.remove(key); - } - } - try { - IStatsd statsd = getStatsdNonblocking(); - if (statsd != null) { - statsd.unsetBroadcastSubscriber(configId, subscriberId, callingUid); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to unsetBroadcastSubscriber with statsd"); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public long[] getRegisteredExperimentIds() throws IllegalStateException { - enforceDumpAndUsageStatsPermission(null); - final long token = Binder.clearCallingIdentity(); - try { - IStatsd statsd = waitForStatsd(); - if (statsd != null) { - return statsd.getRegisteredExperimentIds(); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to getRegisteredExperimentIds with statsd"); - throw new IllegalStateException(e.getMessage(), e); - } finally { - Binder.restoreCallingIdentity(token); - } - throw new IllegalStateException("Failed to connect to statsd to registerExperimentIds"); - } - - @Override - public byte[] getMetadata(String packageName) throws IllegalStateException { - enforceDumpAndUsageStatsPermission(packageName); - final long token = Binder.clearCallingIdentity(); - try { - IStatsd statsd = waitForStatsd(); - if (statsd != null) { - return statsd.getMetadata(); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to getMetadata with statsd"); - throw new IllegalStateException(e.getMessage(), e); - } finally { - Binder.restoreCallingIdentity(token); - } - throw new IllegalStateException("Failed to connect to statsd to getMetadata"); - } - - @Override - public byte[] getData(long key, String packageName) throws IllegalStateException { - enforceDumpAndUsageStatsPermission(packageName); - PowerManager powerManager = (PowerManager) - mContext.getSystemService(Context.POWER_SERVICE); - PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, - /*tag=*/ StatsManagerService.class.getCanonicalName()); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - wl.acquire(); - try { - IStatsd statsd = waitForStatsd(); - if (statsd != null) { - return statsd.getData(key, callingUid); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to getData with statsd"); - throw new IllegalStateException(e.getMessage(), e); - } finally { - wl.release(); - Binder.restoreCallingIdentity(token); - } - throw new IllegalStateException("Failed to connect to statsd to getData"); - } - - @Override - public void addConfiguration(long configId, byte[] config, String packageName) - throws IllegalStateException { - enforceDumpAndUsageStatsPermission(packageName); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - try { - IStatsd statsd = waitForStatsd(); - if (statsd != null) { - statsd.addConfiguration(configId, config, callingUid); - return; - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to addConfiguration with statsd"); - throw new IllegalStateException(e.getMessage(), e); - } finally { - Binder.restoreCallingIdentity(token); - } - throw new IllegalStateException("Failed to connect to statsd to addConfig"); - } - - @Override - public void removeConfiguration(long configId, String packageName) - throws IllegalStateException { - enforceDumpAndUsageStatsPermission(packageName); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - try { - IStatsd statsd = waitForStatsd(); - if (statsd != null) { - statsd.removeConfiguration(configId, callingUid); - return; - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to removeConfiguration with statsd"); - throw new IllegalStateException(e.getMessage(), e); - } finally { - Binder.restoreCallingIdentity(token); - } - throw new IllegalStateException("Failed to connect to statsd to removeConfig"); - } - - void setStatsCompanionService(StatsCompanionService statsCompanionService) { - mStatsCompanionService = statsCompanionService; - } - - /** - * Checks that the caller has both DUMP and PACKAGE_USAGE_STATS permissions. Also checks that - * the caller has USAGE_STATS_PERMISSION_OPS for the specified packageName if it is not null. - * - * @param packageName The packageName to check USAGE_STATS_PERMISSION_OPS. - */ - private void enforceDumpAndUsageStatsPermission(@Nullable String packageName) { - int callingUid = Binder.getCallingUid(); - int callingPid = Binder.getCallingPid(); - - if (callingPid == Process.myPid()) { - return; - } - - mContext.enforceCallingPermission(Manifest.permission.DUMP, null); - mContext.enforceCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS, null); - - if (packageName == null) { - return; - } - AppOpsManager appOpsManager = (AppOpsManager) mContext - .getSystemService(Context.APP_OPS_SERVICE); - switch (appOpsManager.noteOp(USAGE_STATS_PERMISSION_OPS, - Binder.getCallingUid(), packageName, null, null)) { - case AppOpsManager.MODE_ALLOWED: - case AppOpsManager.MODE_DEFAULT: - break; - default: - throw new SecurityException( - String.format("UID %d / PID %d lacks app-op %s", - callingUid, callingPid, USAGE_STATS_PERMISSION_OPS) - ); - } - } - - private void enforceRegisterStatsPullAtomPermission() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.REGISTER_STATS_PULL_ATOM, - "Need REGISTER_STATS_PULL_ATOM permission."); - } - - - /** - * Clients should call this if blocking until statsd to be ready is desired - * - * @return IStatsd object if statsd becomes ready within the timeout, null otherwise. - */ - private IStatsd waitForStatsd() { - synchronized (mLock) { - if (mStatsd == null) { - try { - mLock.wait(STATSD_TIMEOUT_MILLIS); - } catch (InterruptedException e) { - Log.e(TAG, "wait for statsd interrupted"); - } - } - return mStatsd; - } - } - - /** - * Clients should call this to receive a reference to statsd. - * - * @return IStatsd object if statsd is ready, null otherwise. - */ - private IStatsd getStatsdNonblocking() { - synchronized (mLock) { - return mStatsd; - } - } - - /** - * Called from {@link StatsCompanionService}. - * - * Tells StatsManagerService that Statsd is ready and updates - * Statsd with the contents of our local cache. - */ - void statsdReady(IStatsd statsd) { - synchronized (mLock) { - mStatsd = statsd; - mLock.notify(); - } - sayHiToStatsd(statsd); - } - - /** - * Called from {@link StatsCompanionService}. - * - * Tells StatsManagerService that Statsd is no longer ready - * and we should no longer make binder calls with statsd. - */ - void statsdNotReady() { - synchronized (mLock) { - mStatsd = null; - } - } - - private void sayHiToStatsd(IStatsd statsd) { - if (statsd == null) { - return; - } - - final long token = Binder.clearCallingIdentity(); - try { - registerAllPullers(statsd); - registerAllDataFetchOperations(statsd); - registerAllActiveConfigsChangedOperations(statsd); - registerAllBroadcastSubscribers(statsd); - } catch (RemoteException e) { - Log.e(TAG, "StatsManager failed to (re-)register data with statsd"); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - // Pre-condition: the Binder calling identity has already been cleared - private void registerAllPullers(IStatsd statsd) throws RemoteException { - // Since we do not want to make an IPC with the lock held, we first create a copy of the - // data with the lock held before iterating through the map. - ArrayMap<PullerKey, PullerValue> pullersCopy; - synchronized (mLock) { - pullersCopy = new ArrayMap<>(mPullers); - } - - for (Map.Entry<PullerKey, PullerValue> entry : pullersCopy.entrySet()) { - PullerKey key = entry.getKey(); - PullerValue value = entry.getValue(); - statsd.registerPullAtomCallback(key.getUid(), key.getAtom(), value.getCoolDownMillis(), - value.getTimeoutMillis(), value.getAdditiveFields(), value.getCallback()); - } - statsd.allPullersFromBootRegistered(); - } - - // Pre-condition: the Binder calling identity has already been cleared - private void registerAllDataFetchOperations(IStatsd statsd) throws RemoteException { - // Since we do not want to make an IPC with the lock held, we first create a copy of the - // data with the lock held before iterating through the map. - ArrayMap<ConfigKey, PendingIntentRef> dataFetchCopy; - synchronized (mLock) { - dataFetchCopy = new ArrayMap<>(mDataFetchPirMap); - } - - for (Map.Entry<ConfigKey, PendingIntentRef> entry : dataFetchCopy.entrySet()) { - ConfigKey key = entry.getKey(); - statsd.setDataFetchOperation(key.getConfigId(), entry.getValue(), key.getUid()); - } - } - - // Pre-condition: the Binder calling identity has already been cleared - private void registerAllActiveConfigsChangedOperations(IStatsd statsd) throws RemoteException { - // Since we do not want to make an IPC with the lock held, we first create a copy of the - // data with the lock held before iterating through the map. - ArrayMap<Integer, PendingIntentRef> activeConfigsChangedCopy; - synchronized (mLock) { - activeConfigsChangedCopy = new ArrayMap<>(mActiveConfigsPirMap); - } - - for (Map.Entry<Integer, PendingIntentRef> entry : activeConfigsChangedCopy.entrySet()) { - statsd.setActiveConfigsChangedOperation(entry.getValue(), entry.getKey()); - } - } - - // Pre-condition: the Binder calling identity has already been cleared - private void registerAllBroadcastSubscribers(IStatsd statsd) throws RemoteException { - // Since we do not want to make an IPC with the lock held, we first create a deep copy of - // the data with the lock held before iterating through the map. - ArrayMap<ConfigKey, ArrayMap<Long, PendingIntentRef>> broadcastSubscriberCopy = - new ArrayMap<>(); - synchronized (mLock) { - for (Map.Entry<ConfigKey, ArrayMap<Long, PendingIntentRef>> entry : - mBroadcastSubscriberPirMap.entrySet()) { - broadcastSubscriberCopy.put(entry.getKey(), new ArrayMap(entry.getValue())); - } - } - - for (Map.Entry<ConfigKey, ArrayMap<Long, PendingIntentRef>> entry : - mBroadcastSubscriberPirMap.entrySet()) { - ConfigKey configKey = entry.getKey(); - for (Map.Entry<Long, PendingIntentRef> subscriberEntry : entry.getValue().entrySet()) { - statsd.setBroadcastSubscriber(configKey.getConfigId(), subscriberEntry.getKey(), - subscriberEntry.getValue(), configKey.getUid()); - } - } - } -} diff --git a/apex/statsd/statsd.rc b/apex/statsd/statsd.rc deleted file mode 100644 index 605da2af0c19..000000000000 --- a/apex/statsd/statsd.rc +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (C) 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -service statsd /apex/com.android.os.statsd/bin/statsd - class main - socket statsdw dgram+passcred 0222 statsd statsd - user statsd - group statsd log - writepid /dev/cpuset/system-background/tasks diff --git a/apex/statsd/testing/Android.bp b/apex/statsd/testing/Android.bp deleted file mode 100644 index a9cd0ccb53e8..000000000000 --- a/apex/statsd/testing/Android.bp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -apex_test { - name: "test_com.android.os.statsd", - visibility: [ - "//system/apex/tests", - ], - defaults: ["com.android.os.statsd-defaults"], - manifest: "test_manifest.json", - file_contexts: ":com.android.os.statsd-file_contexts", - // Test APEX, should never be installed - installable: false, -} diff --git a/apex/statsd/testing/test_manifest.json b/apex/statsd/testing/test_manifest.json deleted file mode 100644 index 57343d3e6ae5..000000000000 --- a/apex/statsd/testing/test_manifest.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "com.android.os.statsd", - "version": 2147483647 -} diff --git a/apex/statsd/tests/libstatspull/Android.bp b/apex/statsd/tests/libstatspull/Android.bp deleted file mode 100644 index 05b3e049ac39..000000000000 --- a/apex/statsd/tests/libstatspull/Android.bp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -android_test { - name: "LibStatsPullTests", - static_libs: [ - "androidx.test.rules", - "platformprotoslite", - "statsdprotolite", - "truth-prebuilt", - ], - libs: [ - "android.test.runner.stubs", - "android.test.base.stubs", - ], - jni_libs: [ - "libstatspull_testhelper", - ], - srcs: [ - "src/**/*.java", - "protos/**/*.proto", - ], - test_suites: [ - "device-tests", - "mts", - ], - platform_apis: true, - privileged: true, - certificate: "platform", - compile_multilib: "both", -} - -cc_library_shared { - name: "libstatspull_testhelper", - srcs: ["jni/stats_pull_helper.cpp"], - cflags: [ - "-Wall", - "-Werror", - ], - shared_libs: [ - "libbinder_ndk", - "statsd-aidl-ndk_platform", - ], - static_libs: [ - "libstatspull_private", - "libstatssocket_private", - "libutils", - "libcutils", - ], -} diff --git a/apex/statsd/tests/libstatspull/AndroidManifest.xml b/apex/statsd/tests/libstatspull/AndroidManifest.xml deleted file mode 100644 index 0c669b051c86..000000000000 --- a/apex/statsd/tests/libstatspull/AndroidManifest.xml +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - --> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.internal.os.statsd.libstats" > - - - <uses-permission android:name="android.permission.DUMP" /> - <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" /> - <uses-permission android:name="android.permission.REGISTER_STATS_PULL_ATOM" /> - - <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="com.android.internal.os.statsd.libstats" - android:label="Tests for libstatspull"> - </instrumentation> -</manifest> - diff --git a/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp b/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp deleted file mode 100644 index 166592d35151..000000000000 --- a/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2019, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <jni.h> -#include <log/log.h> -#include <stats_event.h> -#include <stats_pull_atom_callback.h> - -#include <chrono> -#include <thread> - -using std::this_thread::sleep_for; - -namespace { -static int32_t sAtomTag; -static int32_t sPullReturnVal; -static int64_t sLatencyMillis; -static int32_t sAtomsPerPull; -static int32_t sNumPulls = 0; - -static AStatsManager_PullAtomCallbackReturn pullAtomCallback(int32_t atomTag, AStatsEventList* data, - void* /*cookie*/) { - sNumPulls++; - sleep_for(std::chrono::milliseconds(sLatencyMillis)); - for (int i = 0; i < sAtomsPerPull; i++) { - AStatsEvent* event = AStatsEventList_addStatsEvent(data); - AStatsEvent_setAtomId(event, atomTag); - AStatsEvent_writeInt64(event, (int64_t) sNumPulls); - AStatsEvent_build(event); - } - return sPullReturnVal; -} - -extern "C" JNIEXPORT void JNICALL -Java_com_android_internal_os_statsd_libstats_LibStatsPullTests_setStatsPuller( - JNIEnv* /*env*/, jobject /* this */, jint atomTag, jlong timeoutMillis, - jlong coolDownMillis, jint pullRetVal, jlong latencyMillis, int atomsPerPull) { - sAtomTag = atomTag; - sPullReturnVal = pullRetVal; - sLatencyMillis = latencyMillis; - sAtomsPerPull = atomsPerPull; - sNumPulls = 0; - AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain(); - AStatsManager_PullAtomMetadata_setCoolDownMillis(metadata, coolDownMillis); - AStatsManager_PullAtomMetadata_setTimeoutMillis(metadata, timeoutMillis); - - AStatsManager_setPullAtomCallback(sAtomTag, metadata, &pullAtomCallback, nullptr); - AStatsManager_PullAtomMetadata_release(metadata); -} - -extern "C" JNIEXPORT void JNICALL -Java_com_android_internal_os_statsd_libstats_LibStatsPullTests_clearStatsPuller(JNIEnv* /*env*/, - jobject /* this */, - jint /*atomTag*/) { - AStatsManager_clearPullAtomCallback(sAtomTag); -} -} // namespace diff --git a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java deleted file mode 100644 index 6108a324e15e..000000000000 --- a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.internal.os.statsd.libstats; - -import static com.google.common.truth.Truth.assertThat; - -import android.app.StatsManager; -import android.content.Context; -import android.util.Log; -import android.util.StatsLog; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.MediumTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.os.StatsdConfigProto.AtomMatcher; -import com.android.internal.os.StatsdConfigProto.FieldFilter; -import com.android.internal.os.StatsdConfigProto.GaugeMetric; -import com.android.internal.os.StatsdConfigProto.PullAtomPackages; -import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher; -import com.android.internal.os.StatsdConfigProto.StatsdConfig; -import com.android.internal.os.StatsdConfigProto.TimeUnit; -import com.android.internal.os.statsd.protos.TestAtoms; -import com.android.os.AtomsProto.Atom; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.List; - -/** - * Test puller registration. - */ -@MediumTest -@RunWith(AndroidJUnit4.class) -public class LibStatsPullTests { - private static final String LOG_TAG = LibStatsPullTests.class.getSimpleName(); - private static final int SHORT_SLEEP_MILLIS = 250; - private static final int LONG_SLEEP_MILLIS = 1_000; - private Context mContext; - private static final int PULL_ATOM_TAG = 150030; - private static final int APP_BREADCRUMB_LABEL = 3; - private static int sPullReturnValue; - private static long sConfigId; - private static long sPullLatencyMillis; - private static long sPullTimeoutMillis; - private static long sCoolDownMillis; - private static int sAtomsPerPull; - - static { - System.loadLibrary("statspull_testhelper"); - } - - /** - * Setup the tests. Initialize shared data. - */ - @Before - public void setup() { - mContext = InstrumentationRegistry.getTargetContext(); - assertThat(InstrumentationRegistry.getInstrumentation()).isNotNull(); - sPullReturnValue = StatsManager.PULL_SUCCESS; - sPullLatencyMillis = 0; - sPullTimeoutMillis = 10_000L; - sCoolDownMillis = 1_000L; - sAtomsPerPull = 1; - } - - /** - * Teardown the tests. - */ - @After - public void tearDown() throws Exception { - clearStatsPuller(PULL_ATOM_TAG); - StatsManager statsManager = (StatsManager) mContext.getSystemService( - Context.STATS_MANAGER); - statsManager.removeConfig(sConfigId); - } - - /** - * Tests adding a puller callback and that pulls complete successfully. - */ - @Test - public void testPullAtomCallbackRegistration() throws Exception { - StatsManager statsManager = (StatsManager) mContext.getSystemService( - Context.STATS_MANAGER); - // Upload a config that captures that pulled atom. - createAndAddConfigToStatsd(statsManager); - - // Add the puller. - setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue, - sPullLatencyMillis, sAtomsPerPull); - Thread.sleep(SHORT_SLEEP_MILLIS); - StatsLog.logStart(APP_BREADCRUMB_LABEL); - // Let the current bucket finish. - Thread.sleep(LONG_SLEEP_MILLIS); - List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId); - clearStatsPuller(PULL_ATOM_TAG); - assertThat(data.size()).isEqualTo(1); - TestAtoms.PullCallbackAtomWrapper atomWrapper = null; - try { - atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser() - .parseFrom(data.get(0).toByteArray()); - } catch (Exception e) { - Log.e(LOG_TAG, "Failed to parse primitive atoms"); - } - assertThat(atomWrapper).isNotNull(); - assertThat(atomWrapper.hasPullCallbackAtom()).isTrue(); - TestAtoms.PullCallbackAtom atom = - atomWrapper.getPullCallbackAtom(); - assertThat(atom.getLongVal()).isEqualTo(1); - } - - /** - * Tests that a failed pull is skipped. - */ - @Test - public void testPullAtomCallbackFailure() throws Exception { - StatsManager statsManager = (StatsManager) mContext.getSystemService( - Context.STATS_MANAGER); - createAndAddConfigToStatsd(statsManager); - sPullReturnValue = StatsManager.PULL_SKIP; - // Add the puller. - setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue, - sPullLatencyMillis, sAtomsPerPull); - Thread.sleep(SHORT_SLEEP_MILLIS); - StatsLog.logStart(APP_BREADCRUMB_LABEL); - // Let the current bucket finish. - Thread.sleep(LONG_SLEEP_MILLIS); - List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId); - clearStatsPuller(PULL_ATOM_TAG); - assertThat(data.size()).isEqualTo(0); - } - - /** - * Tests that a pull that times out is skipped. - */ - @Test - public void testPullAtomCallbackTimeout() throws Exception { - StatsManager statsManager = (StatsManager) mContext.getSystemService( - Context.STATS_MANAGER); - createAndAddConfigToStatsd(statsManager); - // The puller will sleep for 1.5 sec. - sPullLatencyMillis = 1_500; - // 1 second timeout - sPullTimeoutMillis = 1_000; - - // Add the puller. - setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue, - sPullLatencyMillis, sAtomsPerPull); - Thread.sleep(SHORT_SLEEP_MILLIS); - StatsLog.logStart(APP_BREADCRUMB_LABEL); - // Let the current bucket finish and the pull timeout. - Thread.sleep(sPullLatencyMillis * 2); - List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId); - clearStatsPuller(PULL_ATOM_TAG); - assertThat(data.size()).isEqualTo(0); - } - - /** - * Tests that 2 pulls in quick succession use the cache instead of pulling again. - */ - @Test - public void testPullAtomCallbackCache() throws Exception { - StatsManager statsManager = (StatsManager) mContext.getSystemService( - Context.STATS_MANAGER); - createAndAddConfigToStatsd(statsManager); - - // Set the cooldown to 10 seconds - sCoolDownMillis = 10_000L; - // Add the puller. - setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue, - sPullLatencyMillis, sAtomsPerPull); - - Thread.sleep(SHORT_SLEEP_MILLIS); - StatsLog.logStart(APP_BREADCRUMB_LABEL); - // Pull from cache. - StatsLog.logStart(APP_BREADCRUMB_LABEL); - Thread.sleep(LONG_SLEEP_MILLIS); - List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId); - clearStatsPuller(PULL_ATOM_TAG); - assertThat(data.size()).isEqualTo(2); - for (int i = 0; i < data.size(); i++) { - TestAtoms.PullCallbackAtomWrapper atomWrapper = null; - try { - atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser() - .parseFrom(data.get(i).toByteArray()); - } catch (Exception e) { - Log.e(LOG_TAG, "Failed to parse primitive atoms"); - } - assertThat(atomWrapper).isNotNull(); - assertThat(atomWrapper.hasPullCallbackAtom()).isTrue(); - TestAtoms.PullCallbackAtom atom = - atomWrapper.getPullCallbackAtom(); - assertThat(atom.getLongVal()).isEqualTo(1); - } - } - - /** - * Tests that a pull that returns 1000 stats events works properly. - */ - @Test - public void testPullAtomCallbackStress() throws Exception { - StatsManager statsManager = (StatsManager) mContext.getSystemService( - Context.STATS_MANAGER); - // Upload a config that captures that pulled atom. - createAndAddConfigToStatsd(statsManager); - sAtomsPerPull = 1000; - // Add the puller. - setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue, - sPullLatencyMillis, sAtomsPerPull); - - Thread.sleep(SHORT_SLEEP_MILLIS); - StatsLog.logStart(APP_BREADCRUMB_LABEL); - // Let the current bucket finish. - Thread.sleep(LONG_SLEEP_MILLIS); - List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId); - clearStatsPuller(PULL_ATOM_TAG); - assertThat(data.size()).isEqualTo(sAtomsPerPull); - - for (int i = 0; i < data.size(); i++) { - TestAtoms.PullCallbackAtomWrapper atomWrapper = null; - try { - atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser() - .parseFrom(data.get(i).toByteArray()); - } catch (Exception e) { - Log.e(LOG_TAG, "Failed to parse primitive atoms"); - } - assertThat(atomWrapper).isNotNull(); - assertThat(atomWrapper.hasPullCallbackAtom()).isTrue(); - TestAtoms.PullCallbackAtom atom = - atomWrapper.getPullCallbackAtom(); - assertThat(atom.getLongVal()).isEqualTo(1); - } - } - - private void createAndAddConfigToStatsd(StatsManager statsManager) throws Exception { - sConfigId = System.currentTimeMillis(); - long triggerMatcherId = sConfigId + 10; - long pullerMatcherId = sConfigId + 11; - long metricId = sConfigId + 100; - StatsdConfig config = StatsConfigUtils.getSimpleTestConfig(sConfigId) - .addAtomMatcher( - StatsConfigUtils.getAppBreadcrumbMatcher(triggerMatcherId, - APP_BREADCRUMB_LABEL)) - .addAtomMatcher(AtomMatcher.newBuilder() - .setId(pullerMatcherId) - .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder() - .setAtomId(PULL_ATOM_TAG)) - ) - .addGaugeMetric(GaugeMetric.newBuilder() - .setId(metricId) - .setWhat(pullerMatcherId) - .setTriggerEvent(triggerMatcherId) - .setGaugeFieldsFilter(FieldFilter.newBuilder().setIncludeAll(true)) - .setBucket(TimeUnit.CTS) - .setSamplingType(GaugeMetric.SamplingType.FIRST_N_SAMPLES) - .setMaxNumGaugeAtomsPerBucket(1000) - ) - .addPullAtomPackages(PullAtomPackages.newBuilder() - .setAtomId(PULL_ATOM_TAG) - .addPackages(LibStatsPullTests.class.getPackage().getName())) - .build(); - statsManager.addConfig(sConfigId, config.toByteArray()); - assertThat(StatsConfigUtils.verifyValidConfigExists(statsManager, sConfigId)).isTrue(); - } - - private native void setStatsPuller(int atomTag, long timeoutMillis, long coolDownMillis, - int pullReturnVal, long latencyMillis, int atomPerPull); - - private native void clearStatsPuller(int atomTag); -} - diff --git a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/StatsConfigUtils.java b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/StatsConfigUtils.java deleted file mode 100644 index b5afb94886de..000000000000 --- a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/StatsConfigUtils.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.internal.os.statsd.libstats; - -import static com.google.common.truth.Truth.assertThat; - -import android.app.StatsManager; -import android.util.Log; - -import com.android.internal.os.StatsdConfigProto.AtomMatcher; -import com.android.internal.os.StatsdConfigProto.FieldValueMatcher; -import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher; -import com.android.internal.os.StatsdConfigProto.StatsdConfig; -import com.android.os.AtomsProto.AppBreadcrumbReported; -import com.android.os.AtomsProto.Atom; -import com.android.os.StatsLog.ConfigMetricsReport; -import com.android.os.StatsLog.ConfigMetricsReportList; -import com.android.os.StatsLog.GaugeBucketInfo; -import com.android.os.StatsLog.GaugeMetricData; -import com.android.os.StatsLog.StatsLogReport; -import com.android.os.StatsLog.StatsdStatsReport; -import com.android.os.StatsLog.StatsdStatsReport.ConfigStats; - -import java.util.ArrayList; -import java.util.List; - -/** - * Util class for constructing statsd configs. - */ -public class StatsConfigUtils { - public static final String TAG = "statsd.StatsConfigUtils"; - public static final int SHORT_WAIT = 2_000; // 2 seconds. - - /** - * @return An empty StatsdConfig in serialized proto format. - */ - public static StatsdConfig.Builder getSimpleTestConfig(long configId) { - return StatsdConfig.newBuilder().setId(configId) - .addAllowedLogSource(StatsConfigUtils.class.getPackage().getName()); - } - - - public static boolean verifyValidConfigExists(StatsManager statsManager, long configId) { - StatsdStatsReport report = null; - try { - report = StatsdStatsReport.parser().parseFrom(statsManager.getStatsMetadata()); - } catch (Exception e) { - Log.e(TAG, "getMetadata failed", e); - } - assertThat(report).isNotNull(); - boolean foundConfig = false; - for (ConfigStats configStats : report.getConfigStatsList()) { - if (configStats.getId() == configId && configStats.getIsValid() - && configStats.getDeletionTimeSec() == 0) { - foundConfig = true; - } - } - return foundConfig; - } - - public static AtomMatcher getAppBreadcrumbMatcher(long id, int label) { - return AtomMatcher.newBuilder() - .setId(id) - .setSimpleAtomMatcher( - SimpleAtomMatcher.newBuilder() - .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER) - .addFieldValueMatcher(FieldValueMatcher.newBuilder() - .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER) - .setEqInt(label) - ) - ) - .build(); - } - - public static ConfigMetricsReport getConfigMetricsReport(StatsManager statsManager, - long configId) { - ConfigMetricsReportList reportList = null; - try { - reportList = ConfigMetricsReportList.parser() - .parseFrom(statsManager.getReports(configId)); - } catch (Exception e) { - Log.e(TAG, "getData failed", e); - } - assertThat(reportList).isNotNull(); - assertThat(reportList.getReportsCount()).isEqualTo(1); - ConfigMetricsReport report = reportList.getReports(0); - assertThat(report.getDumpReportReason()) - .isEqualTo(ConfigMetricsReport.DumpReportReason.GET_DATA_CALLED); - return report; - - } - public static List<Atom> getGaugeMetricDataList(ConfigMetricsReport report) { - List<Atom> data = new ArrayList<>(); - for (StatsLogReport metric : report.getMetricsList()) { - for (GaugeMetricData gaugeMetricData : metric.getGaugeMetrics().getDataList()) { - for (GaugeBucketInfo bucketInfo : gaugeMetricData.getBucketInfoList()) { - for (Atom atom : bucketInfo.getAtomList()) { - data.add(atom); - } - } - } - } - return data; - } - - public static List<Atom> getGaugeMetricDataList(StatsManager statsManager, long configId) { - ConfigMetricsReport report = getConfigMetricsReport(statsManager, configId); - return getGaugeMetricDataList(report); - } -} - diff --git a/api/OWNERS b/api/OWNERS new file mode 100644 index 000000000000..88d0b61a2ab6 --- /dev/null +++ b/api/OWNERS @@ -0,0 +1 @@ +per-file Android.bp = file:platform/build/soong:/OWNERS diff --git a/cmds/am/OWNERS b/cmds/am/OWNERS new file mode 100644 index 000000000000..72c0a9e6e90c --- /dev/null +++ b/cmds/am/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/am/OWNERS diff --git a/cmds/appops/OWNERS b/cmds/appops/OWNERS new file mode 100644 index 000000000000..999ea0e62a0a --- /dev/null +++ b/cmds/appops/OWNERS @@ -0,0 +1 @@ +include /core/java/android/permission/OWNERS diff --git a/cmds/backup/OWNERS b/cmds/backup/OWNERS new file mode 100644 index 000000000000..d99779e3d9da --- /dev/null +++ b/cmds/backup/OWNERS @@ -0,0 +1 @@ +include /services/backup/OWNERS diff --git a/cmds/bmgr/OWNERS b/cmds/bmgr/OWNERS new file mode 100644 index 000000000000..d99779e3d9da --- /dev/null +++ b/cmds/bmgr/OWNERS @@ -0,0 +1 @@ +include /services/backup/OWNERS diff --git a/cmds/bu/OWNERS b/cmds/bu/OWNERS new file mode 100644 index 000000000000..d99779e3d9da --- /dev/null +++ b/cmds/bu/OWNERS @@ -0,0 +1 @@ +include /services/backup/OWNERS diff --git a/cmds/dpm/OWNERS b/cmds/dpm/OWNERS new file mode 100644 index 000000000000..e95633abe79a --- /dev/null +++ b/cmds/dpm/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/admin/OWNERS diff --git a/cmds/ime/OWNERS b/cmds/ime/OWNERS new file mode 100644 index 000000000000..5deb2ce8f24b --- /dev/null +++ b/cmds/ime/OWNERS @@ -0,0 +1 @@ +include /core/java/android/view/inputmethod/OWNERS diff --git a/cmds/incident/OWNERS b/cmds/incident/OWNERS new file mode 100644 index 000000000000..f76611555dbb --- /dev/null +++ b/cmds/incident/OWNERS @@ -0,0 +1 @@ +include /cmds/incidentd/OWNERS diff --git a/cmds/input/OWNERS b/cmds/input/OWNERS new file mode 100644 index 000000000000..d701f23cb9b8 --- /dev/null +++ b/cmds/input/OWNERS @@ -0,0 +1 @@ +include /core/java/android/hardware/input/OWNERS diff --git a/cmds/locksettings/OWNERS b/cmds/locksettings/OWNERS new file mode 100644 index 000000000000..0a8dc8c45a9f --- /dev/null +++ b/cmds/locksettings/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/locksettings/OWNERS diff --git a/cmds/pm/OWNERS b/cmds/pm/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/cmds/pm/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/cmds/sm/OWNERS b/cmds/sm/OWNERS new file mode 100644 index 000000000000..6f9dbea36b06 --- /dev/null +++ b/cmds/sm/OWNERS @@ -0,0 +1 @@ +include /core/java/android/os/storage/OWNERS diff --git a/cmds/telecom/OWNERS b/cmds/telecom/OWNERS new file mode 100644 index 000000000000..2f813e6aeb7f --- /dev/null +++ b/cmds/telecom/OWNERS @@ -0,0 +1 @@ +include /telecomm/OWNERS diff --git a/cmds/uinput/OWNERS b/cmds/uinput/OWNERS new file mode 100644 index 000000000000..d701f23cb9b8 --- /dev/null +++ b/cmds/uinput/OWNERS @@ -0,0 +1 @@ +include /core/java/android/hardware/input/OWNERS diff --git a/cmds/wm/OWNERS b/cmds/wm/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/cmds/wm/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/config/OWNERS b/config/OWNERS index 3d4924df3462..d59c6f2d72ba 100644 --- a/config/OWNERS +++ b/config/OWNERS @@ -1,4 +1,7 @@ +include /ZYGOTE_OWNERS + # compat-team@ for changes to hiddenapi files + per-file hiddenapi-* = andreionea@google.com, mathewi@google.com, satayev@google.com # Escalations: diff --git a/core/api/OWNERS b/core/api/OWNERS new file mode 100644 index 000000000000..0b95c5155594 --- /dev/null +++ b/core/api/OWNERS @@ -0,0 +1,2 @@ +# API changes are managed via Prolog rules, not OWNERS +* diff --git a/core/api/current.txt b/core/api/current.txt index 8b350f5b7c06..8412bda19236 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -165,6 +165,7 @@ package android { field public static final String USE_BIOMETRIC = "android.permission.USE_BIOMETRIC"; field @Deprecated public static final String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT"; field public static final String USE_FULL_SCREEN_INTENT = "android.permission.USE_FULL_SCREEN_INTENT"; + field public static final String USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER = "android.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER"; field public static final String USE_SIP = "android.permission.USE_SIP"; field public static final String VIBRATE = "android.permission.VIBRATE"; field public static final String WAKE_LOCK = "android.permission.WAKE_LOCK"; @@ -6215,6 +6216,7 @@ package android.app { method public android.app.PictureInPictureParams.Builder setActions(java.util.List<android.app.RemoteAction>); method public android.app.PictureInPictureParams.Builder setAspectRatio(android.util.Rational); method @NonNull public android.app.PictureInPictureParams.Builder setAutoEnterEnabled(boolean); + method @NonNull public android.app.PictureInPictureParams.Builder setSeamlessResizeEnabled(boolean); method public android.app.PictureInPictureParams.Builder setSourceRectHint(android.graphics.Rect); } @@ -6920,6 +6922,7 @@ package android.app.admin { method public int getGlobalPrivateDnsMode(@NonNull android.content.ComponentName); method @NonNull public java.util.List<byte[]> getInstalledCaCerts(@Nullable android.content.ComponentName); method @Nullable public java.util.List<java.lang.String> getKeepUninstalledPackages(@Nullable android.content.ComponentName); + method @NonNull public java.util.Set<java.util.Set<java.lang.String>> getKeyPairGrants(@NonNull String); method public int getKeyguardDisabledFeatures(@Nullable android.content.ComponentName); method public int getLockTaskFeatures(@NonNull android.content.ComponentName); method @NonNull public String[] getLockTaskPackages(@NonNull android.content.ComponentName); @@ -12453,6 +12456,7 @@ package android.content.pm { field public static final int PROTECTION_FLAG_SETUP = 2048; // 0x800 field @Deprecated public static final int PROTECTION_FLAG_SYSTEM = 16; // 0x10 field public static final int PROTECTION_FLAG_VERIFIER = 512; // 0x200 + field public static final int PROTECTION_INTERNAL = 4; // 0x4 field @Deprecated public static final int PROTECTION_MASK_BASE = 15; // 0xf field @Deprecated public static final int PROTECTION_MASK_FLAGS = 65520; // 0xfff0 field public static final int PROTECTION_NORMAL = 0; // 0x0 @@ -15275,16 +15279,11 @@ package android.graphics { ctor public PaintFlagsDrawFilter(int, int); } - public final class ParcelableColorSpace extends android.graphics.ColorSpace implements android.os.Parcelable { + public final class ParcelableColorSpace implements android.os.Parcelable { ctor public ParcelableColorSpace(@NonNull android.graphics.ColorSpace); method public int describeContents(); - method @NonNull public float[] fromXyz(@NonNull float[]); method @NonNull public android.graphics.ColorSpace getColorSpace(); - method public float getMaxValue(int); - method public float getMinValue(int); method public static boolean isParcelable(@NonNull android.graphics.ColorSpace); - method public boolean isWideGamut(); - method @NonNull public float[] toXyz(@NonNull float[]); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.graphics.ParcelableColorSpace> CREATOR; } @@ -24032,7 +24031,7 @@ package android.location { method public void setBearingAccuracyDegrees(float); method public void setElapsedRealtimeNanos(long); method public void setElapsedRealtimeUncertaintyNanos(double); - method @Deprecated public void setExtras(android.os.Bundle); + method @Deprecated public void setExtras(@Nullable android.os.Bundle); method public void setLatitude(double); method public void setLongitude(double); method public void setProvider(String); @@ -24305,6 +24304,7 @@ package android.media { public final class AudioDeviceInfo { method @NonNull public String getAddress(); + method @NonNull public java.util.List<android.media.AudioProfile> getAudioProfiles(); method @NonNull public int[] getChannelCounts(); method @NonNull public int[] getChannelIndexMasks(); method @NonNull public int[] getChannelMasks(); @@ -24722,6 +24722,13 @@ package android.media { method @NonNull public android.media.AudioPresentation.Builder setProgramId(int); } + public class AudioProfile { + method @NonNull public int[] getChannelIndexMasks(); + method @NonNull public int[] getChannelMasks(); + method public int getFormat(); + method @NonNull public int[] getSampleRates(); + } + public class AudioRecord implements android.media.AudioRecordingMonitor android.media.AudioRouting android.media.MicrophoneDirection { ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException; method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); @@ -28899,6 +28906,7 @@ package android.media.session { field public static final long ACTION_PREPARE_FROM_URI = 131072L; // 0x20000L field public static final long ACTION_REWIND = 8L; // 0x8L field public static final long ACTION_SEEK_TO = 256L; // 0x100L + field public static final long ACTION_SET_PLAYBACK_SPEED = 4194304L; // 0x400000L field public static final long ACTION_SET_RATING = 128L; // 0x80L field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L @@ -34862,6 +34870,27 @@ package android.os { method public void onCancel(); } + public abstract class CombinedVibrationEffect implements android.os.Parcelable { + method @NonNull public static android.os.CombinedVibrationEffect createSynced(@NonNull android.os.VibrationEffect); + method public int describeContents(); + method @NonNull public static android.os.CombinedVibrationEffect.SequentialCombination startSequential(); + method @NonNull public static android.os.CombinedVibrationEffect.SyncedCombination startSynced(); + field @NonNull public static final android.os.Parcelable.Creator<android.os.CombinedVibrationEffect> CREATOR; + } + + public static final class CombinedVibrationEffect.SequentialCombination { + method @NonNull public android.os.CombinedVibrationEffect.SequentialCombination addNext(int, @NonNull android.os.VibrationEffect); + method @NonNull public android.os.CombinedVibrationEffect.SequentialCombination addNext(int, @NonNull android.os.VibrationEffect, int); + method @NonNull public android.os.CombinedVibrationEffect.SequentialCombination addNext(@NonNull android.os.CombinedVibrationEffect); + method @NonNull public android.os.CombinedVibrationEffect.SequentialCombination addNext(@NonNull android.os.CombinedVibrationEffect, int); + method @NonNull public android.os.CombinedVibrationEffect combine(); + } + + public static final class CombinedVibrationEffect.SyncedCombination { + method @NonNull public android.os.CombinedVibrationEffect.SyncedCombination addVibrator(int, @NonNull android.os.VibrationEffect); + method @NonNull public android.os.CombinedVibrationEffect combine(); + } + public class ConditionVariable { ctor public ConditionVariable(); ctor public ConditionVariable(boolean); @@ -36088,6 +36117,13 @@ package android.os { field public static final int VIBRATION_EFFECT_SUPPORT_YES = 1; // 0x1 } + public abstract class VibratorManager { + method @NonNull public abstract android.os.Vibrator getDefaultVibrator(); + method @NonNull public abstract android.os.Vibrator getVibrator(int); + method @NonNull public abstract int[] getVibratorIds(); + method public abstract void vibrate(@NonNull android.os.CombinedVibrationEffect); + } + public class WorkSource implements android.os.Parcelable { ctor public WorkSource(); ctor public WorkSource(android.os.WorkSource); @@ -47014,7 +47050,6 @@ package android.telephony { method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle); method public boolean isWorldPhone(); method @Deprecated public void listen(android.telephony.PhoneStateListener, int); - method @Deprecated public void listen(long, @NonNull android.telephony.PhoneStateListener); method public void registerPhoneStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.PhoneStateListener); method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestCellInfoUpdate(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback); method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback); @@ -47058,6 +47093,7 @@ package android.telephony { field public static final int APPTYPE_ISIM = 5; // 0x5 field public static final int APPTYPE_RUIM = 3; // 0x3 field public static final int APPTYPE_SIM = 1; // 0x1 + field public static final int APPTYPE_UNKNOWN = 0; // 0x0 field public static final int APPTYPE_USIM = 2; // 0x2 field public static final int AUTHTYPE_EAP_AKA = 129; // 0x81 field public static final int AUTHTYPE_EAP_SIM = 128; // 0x80 @@ -47784,6 +47820,7 @@ package android.telephony.ims { field public static final int CODE_WIFI_LOST = 1407; // 0x57f field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsReasonInfo> CREATOR; field public static final int EXTRA_CODE_CALL_RETRY_BY_SETTINGS = 3; // 0x3 + field public static final int EXTRA_CODE_CALL_RETRY_EMERGENCY = 4; // 0x4 field public static final int EXTRA_CODE_CALL_RETRY_NORMAL = 1; // 0x1 field public static final int EXTRA_CODE_CALL_RETRY_SILENT_REDIAL = 2; // 0x2 } @@ -51336,6 +51373,7 @@ package android.view { method public int getSources(); method public int getVendorId(); method public android.os.Vibrator getVibrator(); + method @NonNull public android.os.VibratorManager getVibratorManager(); method public boolean[] hasKeys(int...); method public boolean hasMicrophone(); method public boolean isEnabled(); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index c3bf05813b90..98dd42de8212 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -36,6 +36,7 @@ package android { field public static final String BIND_DIRECTORY_SEARCH = "android.permission.BIND_DIRECTORY_SEARCH"; field public static final String BIND_EUICC_SERVICE = "android.permission.BIND_EUICC_SERVICE"; field public static final String BIND_EXTERNAL_STORAGE_SERVICE = "android.permission.BIND_EXTERNAL_STORAGE_SERVICE"; + field public static final String BIND_GBA_SERVICE = "android.permission.BIND_GBA_SERVICE"; field public static final String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE"; field public static final String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET"; field public static final String BIND_MUSIC_RECOGNITION_SERVICE = "android.permission.BIND_MUSIC_RECOGNITION_SERVICE"; @@ -56,6 +57,7 @@ package android { field public static final String BRIGHTNESS_SLIDER_USAGE = "android.permission.BRIGHTNESS_SLIDER_USAGE"; field @Deprecated public static final String BROADCAST_NETWORK_PRIVILEGED = "android.permission.BROADCAST_NETWORK_PRIVILEGED"; field public static final String CAMERA_DISABLE_TRANSMIT_LED = "android.permission.CAMERA_DISABLE_TRANSMIT_LED"; + field public static final String CAMERA_OPEN_CLOSE_LISTENER = "android.permission.CAMERA_OPEN_CLOSE_LISTENER"; field public static final String CAPTURE_AUDIO_HOTWORD = "android.permission.CAPTURE_AUDIO_HOTWORD"; field public static final String CAPTURE_MEDIA_OUTPUT = "android.permission.CAPTURE_MEDIA_OUTPUT"; field public static final String CAPTURE_TV_INPUT = "android.permission.CAPTURE_TV_INPUT"; @@ -210,6 +212,7 @@ package android { field public static final String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT"; field public static final String REVIEW_ACCESSIBILITY_SERVICES = "android.permission.REVIEW_ACCESSIBILITY_SERVICES"; field public static final String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS"; + field public static final String ROTATE_SURFACE_FLINGER = "android.permission.ROTATE_SURFACE_FLINGER"; field public static final String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS"; field public static final String SECURE_ELEMENT_PRIVILEGED_OPERATION = "android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION"; field public static final String SEND_CATEGORY_CAR_NOTIFICATIONS = "android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS"; @@ -607,7 +610,10 @@ package android.app { method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean); method public void setDontSendToRestrictedApps(boolean); method @RequiresPermission(anyOf={android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppWhitelistDuration(long); + method @RequiresPermission(anyOf={android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppWhitelistDuration(int, long); method public android.os.Bundle toBundle(); + field public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 0; // 0x0 + field public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED = 1; // 0x1 } public class DownloadManager { @@ -2291,6 +2297,7 @@ package android.content.pm { field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000 field public static final int PROTECTION_FLAG_RECENTS = 33554432; // 0x2000000 field public static final int PROTECTION_FLAG_RETAIL_DEMO = 16777216; // 0x1000000 + field public static final int PROTECTION_FLAG_ROLE = 67108864; // 0x4000000 field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000 field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000 field @Nullable public final String backgroundPermission; @@ -2454,6 +2461,11 @@ package android.hardware.camera2 { field public static final int SESSION_OPERATION_MODE_VENDOR_START = 32768; // 0x8000 } + public abstract static class CameraManager.AvailabilityCallback { + method @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraClosed(@NonNull String); + method @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraOpened(@NonNull String, @NonNull String); + } + } package android.hardware.camera2.params { @@ -4116,6 +4128,22 @@ package android.location { method @Deprecated public void onStatusChanged(int); } + public final class LastLocationRequest implements android.os.Parcelable { + method public int describeContents(); + method public boolean isHiddenFromAppOps(); + method public boolean isLocationSettingsIgnored(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.location.LastLocationRequest> CREATOR; + } + + public static final class LastLocationRequest.Builder { + ctor public LastLocationRequest.Builder(); + ctor public LastLocationRequest.Builder(@NonNull android.location.LastLocationRequest); + method @NonNull public android.location.LastLocationRequest build(); + method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LastLocationRequest.Builder setHiddenFromAppOps(boolean); + method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LastLocationRequest.Builder setLocationSettingsIgnored(boolean); + } + public class Location implements android.os.Parcelable { method public boolean isComplete(); method public void makeComplete(); @@ -4128,6 +4156,7 @@ package android.location { method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>); method @Nullable public String getExtraLocationControllerPackage(); method @Deprecated public int getGnssBatchSize(); + method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String, @NonNull android.location.LastLocationRequest); method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void injectGnssMeasurementCorrections(@NonNull android.location.GnssMeasurementCorrections); method public boolean isExtraLocationControllerPackageEnabled(); method public boolean isLocationEnabledForUser(@NonNull android.os.UserHandle); @@ -4350,6 +4379,7 @@ package android.media { field public static final int PLAYER_STATE_STARTED = 2; // 0x2 field public static final int PLAYER_STATE_STOPPED = 4; // 0x4 field public static final int PLAYER_STATE_UNKNOWN = -1; // 0xffffffff + field public static final int PLAYER_TYPE_AAUDIO = 13; // 0xd field public static final int PLAYER_TYPE_JAM_AUDIOTRACK = 1; // 0x1 field public static final int PLAYER_TYPE_JAM_MEDIAPLAYER = 2; // 0x2 field public static final int PLAYER_TYPE_JAM_SOUNDPOOL = 3; // 0x3 @@ -4996,6 +5026,7 @@ package android.media.tv.tuner { public class Descrambler implements java.lang.AutoCloseable { method public int addPid(int, int, @Nullable android.media.tv.tuner.filter.Filter); method public void close(); + method public static boolean isValidKeyToken(@NonNull byte[]); method public int removePid(int, int, @Nullable android.media.tv.tuner.filter.Filter); method public int setKeyToken(@NonNull byte[]); field public static final int PID_TYPE_MMTP = 2; // 0x2 @@ -5070,7 +5101,6 @@ package android.media.tv.tuner { field public static final int INVALID_FIRST_MACROBLOCK_IN_SLICE = -1; // 0xffffffff field public static final int INVALID_FRONTEND_ID = -1; // 0xffffffff field public static final int INVALID_FRONTEND_SETTING_FREQUENCY = -1; // 0xffffffff - field @NonNull public static final byte[] INVALID_KEYTOKEN; field public static final int INVALID_LTS_ID = -1; // 0xffffffff field public static final int INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM = -1; // 0xffffffff field public static final int INVALID_STREAM_ID = 65535; // 0xffff @@ -5086,6 +5116,7 @@ package android.media.tv.tuner { field public static final int SCAN_TYPE_AUTO = 1; // 0x1 field public static final int SCAN_TYPE_BLIND = 2; // 0x2 field public static final int SCAN_TYPE_UNDEFINED = 0; // 0x0 + field @NonNull public static final byte[] VOID_KEYTOKEN; } public static interface Tuner.OnResourceLostListener { @@ -5890,8 +5921,8 @@ package android.media.tv.tuner.frontend { public class DvbsFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings { method @NonNull public static android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder builder(); + method public boolean canHandleDiseqcRxMessage(); method @Nullable public android.media.tv.tuner.frontend.DvbsCodeRate getCodeRate(); - method public boolean getCouldHandleDiseqcRxMessage(); method public int getInputStreamId(); method public int getModulation(); method public int getPilot(); @@ -5943,8 +5974,8 @@ package android.media.tv.tuner.frontend { public static class DvbsFrontendSettings.Builder { method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings build(); + method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setCanHandleDiseqcRxMessage(boolean); method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setCodeRate(@Nullable android.media.tv.tuner.frontend.DvbsCodeRate); - method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setCouldHandleDiseqcRxMessage(boolean); method @IntRange(from=1) @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setFrequency(int); method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setInputStreamId(int); method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setModulation(int); @@ -7818,7 +7849,7 @@ package android.os { method @Nullable public <T extends android.os.Parcelable> T getParcelable(@NonNull Class<T>); method public int getStability(); method public void readFromParcel(@NonNull android.os.Parcel); - method public boolean setParcelable(@Nullable android.os.Parcelable); + method public void setParcelable(@Nullable android.os.Parcelable); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.os.ParcelableHolder> CREATOR; } @@ -10870,6 +10901,7 @@ package android.telephony { } public class TelephonyManager { + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void bootstrapAuthenticationRequest(int, @NonNull android.net.Uri, @NonNull android.telephony.gba.UaSecurityProtocolIdentifier, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.BootstrapAuthenticationCallback); method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult changeIccLockPin(@NonNull String, @NonNull String); method public int checkCarrierPrivilegesForPackage(String); @@ -10989,8 +11021,10 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRadioEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int); + method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>); method @Deprecated public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean); @@ -11040,6 +11074,12 @@ package android.telephony { field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE"; field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL"; field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING"; + field public static final int GBA_FAILURE_REASON_FEATURE_NOT_READY = 2; // 0x2 + field public static final int GBA_FAILURE_REASON_FEATURE_NOT_SUPPORTED = 1; // 0x1 + field public static final int GBA_FAILURE_REASON_INCORRECT_NAF_ID = 4; // 0x4 + field public static final int GBA_FAILURE_REASON_NETWORK_FAILURE = 3; // 0x3 + field public static final int GBA_FAILURE_REASON_SECURITY_PROTOCOL_NOT_SUPPORTED = 5; // 0x5 + field public static final int GBA_FAILURE_REASON_UNKNOWN = 0; // 0x0 field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff field public static final int KEY_TYPE_EPDG = 1; // 0x1 field public static final int KEY_TYPE_WLAN = 2; // 0x2 @@ -11074,6 +11114,11 @@ package android.telephony { field public static final int SET_CARRIER_RESTRICTION_ERROR = 2; // 0x2 field public static final int SET_CARRIER_RESTRICTION_NOT_SUPPORTED = 1; // 0x1 field public static final int SET_CARRIER_RESTRICTION_SUCCESS = 0; // 0x0 + field public static final int SET_SIM_POWER_STATE_ALREADY_IN_STATE = 1; // 0x1 + field public static final int SET_SIM_POWER_STATE_MODEM_ERROR = 2; // 0x2 + field public static final int SET_SIM_POWER_STATE_NOT_SUPPORTED = 4; // 0x4 + field public static final int SET_SIM_POWER_STATE_SIM_ERROR = 3; // 0x3 + field public static final int SET_SIM_POWER_STATE_SUCCESS = 0; // 0x0 field public static final int SIM_ACTIVATION_STATE_ACTIVATED = 2; // 0x2 field public static final int SIM_ACTIVATION_STATE_ACTIVATING = 1; // 0x1 field public static final int SIM_ACTIVATION_STATE_DEACTIVATED = 3; // 0x3 @@ -11093,6 +11138,12 @@ package android.telephony { field public static final int THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR = 4; // 0x4 } + public static class TelephonyManager.BootstrapAuthenticationCallback { + ctor public TelephonyManager.BootstrapAuthenticationCallback(); + method public void onAuthenticationFailure(int); + method public void onKeysAvailable(@NonNull byte[], @NonNull String); + } + public static interface TelephonyManager.CallForwardingInfoCallback { method public void onCallForwardingInfoAvailable(@NonNull android.telephony.CallForwardingInfo); method public void onError(int); @@ -11535,6 +11586,141 @@ package android.telephony.euicc { } +package android.telephony.gba { + + public class GbaService extends android.app.Service { + ctor public GbaService(); + method public void onAuthenticationRequest(int, int, int, @NonNull android.net.Uri, @NonNull byte[], boolean); + method public final void reportAuthenticationFailure(int, int) throws java.lang.RuntimeException; + method public final void reportKeysAvailable(int, @NonNull byte[], @NonNull String) throws java.lang.RuntimeException; + field public static final String SERVICE_INTERFACE = "android.telephony.gba.GbaService"; + } + + public class TlsParams { + method public static boolean isTlsCipherSuiteSupported(int); + field public static final int GROUP_SECP256R1 = 23; // 0x17 + field public static final int GROUP_SECP384R1 = 24; // 0x18 + field public static final int GROUP_X25519 = 29; // 0x1d + field public static final int GROUP_X448 = 30; // 0x1e + field public static final int PROTOCOL_VERSION_TLS_1_2 = 771; // 0x303 + field public static final int PROTOCOL_VERSION_TLS_1_3 = 772; // 0x304 + field public static final int SIG_ECDSA_BRAINPOOLP256R1TLS13_SHA256 = 2074; // 0x81a + field public static final int SIG_ECDSA_BRAINPOOLP384R1TLS13_SHA384 = 2075; // 0x81b + field public static final int SIG_ECDSA_BRAINPOOLP512R1TLS13_SHA512 = 2076; // 0x81c + field public static final int SIG_ECDSA_SECP256R1_SHA256 = 1027; // 0x403 + field public static final int SIG_ECDSA_SECP384R1_SHA384 = 1283; // 0x503 + field public static final int SIG_ECDSA_SECP521R1_SHA512 = 1539; // 0x603 + field public static final int SIG_ECDSA_SHA1 = 515; // 0x203 + field public static final int SIG_RSA_PKCS1_SHA1 = 513; // 0x201 + field public static final int SIG_RSA_PKCS1_SHA256 = 1025; // 0x401 + field public static final int SIG_RSA_PKCS1_SHA256_LEGACY = 1056; // 0x420 + field public static final int SIG_RSA_PKCS1_SHA384 = 1281; // 0x501 + field public static final int SIG_RSA_PKCS1_SHA384_LEGACY = 1312; // 0x520 + field public static final int SIG_RSA_PKCS1_SHA512 = 1537; // 0x601 + field public static final int SIG_RSA_PKCS1_SHA512_LEGACY = 1568; // 0x620 + field public static final int SIG_RSA_PSS_RSAE_SHA256 = 2052; // 0x804 + field public static final int SIG_RSA_PSS_RSAE_SHA384 = 2053; // 0x805 + field public static final int SIG_RSA_PSS_RSAE_SHA512 = 2054; // 0x806 + field public static final int TLS_AES_128_CCM_SHA256 = 4868; // 0x1304 + field public static final int TLS_AES_128_GCM_SHA256 = 4865; // 0x1301 + field public static final int TLS_AES_256_GCM_SHA384 = 4866; // 0x1302 + field public static final int TLS_CHACHA20_POLY1305_SHA256 = 4867; // 0x1303 + field public static final int TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 19; // 0x13 + field public static final int TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 50; // 0x32 + field public static final int TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 64; // 0x40 + field public static final int TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 56; // 0x38 + field public static final int TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 106; // 0x6a + field public static final int TLS_DHE_PSK_WITH_AES_128_CCM = 49318; // 0xc0a6 + field public static final int TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 170; // 0xaa + field public static final int TLS_DHE_PSK_WITH_AES_256_CCM = 49319; // 0xc0a7 + field public static final int TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 171; // 0xab + field public static final int TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 52397; // 0xccad + field public static final int TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 22; // 0x16 + field public static final int TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 51; // 0x33 + field public static final int TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 103; // 0x67 + field public static final int TLS_DHE_RSA_WITH_AES_128_CCM = 49310; // 0xc09e + field public static final int TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 158; // 0x9e + field public static final int TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 57; // 0x39 + field public static final int TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 107; // 0x6b + field public static final int TLS_DHE_RSA_WITH_AES_256_CCM = 49311; // 0xc09f + field public static final int TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 159; // 0x9f + field public static final int TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 52394; // 0xccaa + field public static final int TLS_DH_ANON_WITH_3DES_EDE_CBC_SHA = 27; // 0x1b + field public static final int TLS_DH_ANON_WITH_AES_128_CBC_SHA = 52; // 0x34 + field public static final int TLS_DH_ANON_WITH_AES_128_CBC_SHA256 = 108; // 0x6c + field public static final int TLS_DH_ANON_WITH_AES_256_CBC_SHA = 58; // 0x3a + field public static final int TLS_DH_ANON_WITH_AES_256_CBC_SHA256 = 109; // 0x6d + field public static final int TLS_DH_ANON_WITH_RC4_128_MD5 = 24; // 0x18 + field public static final int TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 13; // 0xd + field public static final int TLS_DH_DSS_WITH_AES_128_CBC_SHA = 48; // 0x30 + field public static final int TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 62; // 0x3e + field public static final int TLS_DH_DSS_WITH_AES_256_CBC_SHA = 54; // 0x36 + field public static final int TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 104; // 0x68 + field public static final int TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 16; // 0x10 + field public static final int TLS_DH_RSA_WITH_AES_128_CBC_SHA = 49; // 0x31 + field public static final int TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 63; // 0x3f + field public static final int TLS_DH_RSA_WITH_AES_256_CBC_SHA = 55; // 0x37 + field public static final int TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 105; // 0x69 + field public static final int TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 49195; // 0xc02b + field public static final int TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 49196; // 0xc02c + field public static final int TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 52393; // 0xcca9 + field public static final int TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256 = 53253; // 0xd005 + field public static final int TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 = 53249; // 0xd001 + field public static final int TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384 = 53250; // 0xd002 + field public static final int TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 52396; // 0xccac + field public static final int TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 49199; // 0xc02f + field public static final int TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 49200; // 0xc030 + field public static final int TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 52392; // 0xcca8 + field public static final int TLS_NULL_WITH_NULL_NULL = 0; // 0x0 + field public static final int TLS_RSA_WITH_3DES_EDE_CBC_SHA = 10; // 0xa + field public static final int TLS_RSA_WITH_AES_128_CBC_SHA = 47; // 0x2f + field public static final int TLS_RSA_WITH_AES_128_CBC_SHA256 = 60; // 0x3c + field public static final int TLS_RSA_WITH_AES_256_CBC_SHA = 53; // 0x35 + field public static final int TLS_RSA_WITH_AES_256_CBC_SHA256 = 61; // 0x3d + field public static final int TLS_RSA_WITH_NULL_MD5 = 1; // 0x1 + field public static final int TLS_RSA_WITH_NULL_SHA = 2; // 0x2 + field public static final int TLS_RSA_WITH_NULL_SHA256 = 59; // 0x3b + field public static final int TLS_RSA_WITH_RC4_128_MD5 = 4; // 0x4 + field public static final int TLS_RSA_WITH_RC4_128_SHA = 5; // 0x5 + } + + public final class UaSecurityProtocolIdentifier implements android.os.Parcelable { + method public int describeContents(); + method public int getOrg(); + method public int getProtocol(); + method public int getTlsCipherSuite(); + method @NonNull public byte[] toByteArray(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.gba.UaSecurityProtocolIdentifier> CREATOR; + field public static final int ORG_3GPP = 1; // 0x1 + field public static final int ORG_3GPP2 = 2; // 0x2 + field public static final int ORG_GSMA = 4; // 0x4 + field public static final int ORG_LOCAL = 255; // 0xff + field public static final int ORG_NONE = 0; // 0x0 + field public static final int ORG_OMA = 3; // 0x3 + field public static final int UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI = 256; // 0x100 + field public static final int UA_SECURITY_PROTOCOL_3GPP_GENERIC_PUSH_LAYER = 5; // 0x5 + field public static final int UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS = 3; // 0x3 + field public static final int UA_SECURITY_PROTOCOL_3GPP_HTTP_DIGEST_AUTHENTICATION = 2; // 0x2 + field public static final int UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE = 6; // 0x6 + field public static final int UA_SECURITY_PROTOCOL_3GPP_MBMS = 1; // 0x1 + field public static final int UA_SECURITY_PROTOCOL_3GPP_SIP_BASED_MBMS = 4; // 0x4 + field public static final int UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE = 0; // 0x0 + field public static final int UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER = 131072; // 0x20000 + field public static final int UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT = 65536; // 0x10000 + } + + public static final class UaSecurityProtocolIdentifier.Builder { + ctor public UaSecurityProtocolIdentifier.Builder(); + ctor public UaSecurityProtocolIdentifier.Builder(@NonNull android.telephony.gba.UaSecurityProtocolIdentifier); + method @NonNull public android.telephony.gba.UaSecurityProtocolIdentifier build(); + method @NonNull public android.telephony.gba.UaSecurityProtocolIdentifier.Builder setOrg(int); + method @NonNull public android.telephony.gba.UaSecurityProtocolIdentifier.Builder setProtocol(int); + method @NonNull public android.telephony.gba.UaSecurityProtocolIdentifier.Builder setTlsCipherSuite(int); + } + +} + package android.telephony.ims { public final class AudioCodecAttributes implements android.os.Parcelable { diff --git a/core/api/test-current.txt b/core/api/test-current.txt index a448435926d9..eef73c1f6089 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -216,6 +216,7 @@ package android.app { field public static final String KEY_FG_SERVICE_STATE_SETTLE_TIME = "fg_service_state_settle_time"; field public static final String KEY_TOP_STATE_SETTLE_TIME = "top_state_settle_time"; field public static final String OPSTR_MANAGE_ONGOING_CALLS = "android:manage_ongoing_calls"; + field public static final String OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER = "android:use_icc_auth_with_device_identifier"; field public static final int OP_COARSE_LOCATION = 0; // 0x0 field public static final int OP_RECORD_AUDIO = 27; // 0x1b field public static final int OP_START_FOREGROUND = 76; // 0x4c @@ -272,6 +273,7 @@ package android.app { method public void allowAssistantAdjustment(String); method public void disallowAssistantAdjustment(String); method public android.content.ComponentName getEffectsSuppressor(); + method public boolean isNotificationPolicyAccessGrantedForPackage(@NonNull String); method public boolean matchesCallFilter(android.os.Bundle); method @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted(@NonNull android.content.ComponentName, boolean, boolean); method public void updateNotificationChannel(@NonNull String, int, @NonNull android.app.NotificationChannel); @@ -281,6 +283,7 @@ package android.app { method public java.util.List<android.app.RemoteAction> getActions(); method public float getAspectRatio(); method public android.graphics.Rect getSourceRectHint(); + method public boolean isSeamlessResizeEnabled(); } public class StatusBarManager { @@ -377,6 +380,7 @@ package android.app.admin { field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED"; field public static final int OPERATION_CREATE_AND_MANAGE_USER = 5; // 0x5 field public static final int OPERATION_LOCK_NOW = 1; // 0x1 + field public static final int OPERATION_REBOOT = 7; // 0x7 field public static final int OPERATION_REMOVE_USER = 6; // 0x6 field public static final int OPERATION_START_USER_IN_BACKGROUND = 3; // 0x3 field public static final int OPERATION_STOP_USER = 4; // 0x4 @@ -739,6 +743,11 @@ package android.hardware.camera2 { method public String[] getCameraIdListNoLazy() throws android.hardware.camera2.CameraAccessException; } + public abstract static class CameraManager.AvailabilityCallback { + method @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraClosed(@NonNull String); + method @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraOpened(@NonNull String, @NonNull String); + } + } package android.hardware.display { diff --git a/core/java/android/accounts/ChooseAccountActivity.java b/core/java/android/accounts/ChooseAccountActivity.java index 4af22bfac92d..b27d9cda9f97 100644 --- a/core/java/android/accounts/ChooseAccountActivity.java +++ b/core/java/android/accounts/ChooseAccountActivity.java @@ -16,16 +16,12 @@ package android.accounts; import android.app.Activity; -import android.app.ActivityManager; -import android.app.ActivityTaskManager; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.os.IBinder; import android.os.Parcelable; -import android.os.RemoteException; import android.os.Process; import android.os.UserHandle; import android.util.Log; @@ -71,15 +67,8 @@ public class ChooseAccountActivity extends Activity { return; } - try { - IBinder activityToken = getActivityToken(); - mCallingUid = ActivityTaskManager.getService().getLaunchedFromUid(activityToken); - mCallingPackage = ActivityTaskManager.getService().getLaunchedFromPackage( - activityToken); - } catch (RemoteException re) { - // Couldn't figure out caller details - Log.w(getClass().getSimpleName(), "Unable to get caller identity \n" + re); - } + mCallingUid = getLaunchedFromUid(); + mCallingPackage = getLaunchedFromPackage(); if (UserHandle.isSameApp(mCallingUid, Process.SYSTEM_UID) && getIntent().getStringExtra(AccountManager.KEY_ANDROID_PACKAGE_NAME) != null) { diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java index 4b4ef002ae06..a2464d54f780 100644 --- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java +++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java @@ -15,16 +15,12 @@ */ package android.accounts; -import android.app.ActivityTaskManager; import com.google.android.collect.Sets; import android.app.Activity; -import android.app.ActivityManager; import android.content.Intent; import android.os.Bundle; -import android.os.IBinder; import android.os.Parcelable; -import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.text.TextUtils; @@ -144,22 +140,13 @@ public class ChooseTypeAndAccountActivity extends Activity + savedInstanceState + ")"); } - String message = null; - - try { - IBinder activityToken = getActivityToken(); - mCallingUid = ActivityTaskManager.getService().getLaunchedFromUid(activityToken); - mCallingPackage = ActivityTaskManager.getService().getLaunchedFromPackage( - activityToken); - if (mCallingUid != 0 && mCallingPackage != null) { - Bundle restrictions = UserManager.get(this) - .getUserRestrictions(new UserHandle(UserHandle.getUserId(mCallingUid))); - mDisallowAddAccounts = - restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false); - } - } catch (RemoteException re) { - // Couldn't figure out caller details - Log.w(getClass().getSimpleName(), "Unable to get caller identity \n" + re); + mCallingUid = getLaunchedFromUid(); + mCallingPackage = getLaunchedFromPackage(); + if (mCallingUid != 0 && mCallingPackage != null) { + Bundle restrictions = UserManager.get(this) + .getUserRestrictions(new UserHandle(UserHandle.getUserId(mCallingUid))); + mDisallowAddAccounts = + restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false); } // save some items we use frequently diff --git a/core/java/android/accounts/GrantCredentialsPermissionActivity.java b/core/java/android/accounts/GrantCredentialsPermissionActivity.java index 5dc6e602e5d6..74dae0ecceb7 100644 --- a/core/java/android/accounts/GrantCredentialsPermissionActivity.java +++ b/core/java/android/accounts/GrantCredentialsPermissionActivity.java @@ -16,18 +16,14 @@ package android.accounts; import android.app.Activity; -import android.app.ActivityTaskManager; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Resources; import android.os.Bundle; -import android.os.IBinder; import android.os.Process; -import android.os.RemoteException; import android.os.UserHandle; import android.text.TextUtils; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.LinearLayout; @@ -85,13 +81,7 @@ public class GrantCredentialsPermissionActivity extends Activity implements View return; } - try { - IBinder activityToken = getActivityToken(); - mCallingUid = ActivityTaskManager.getService().getLaunchedFromUid(activityToken); - } catch (RemoteException re) { - // Couldn't figure out caller details - Log.w(getClass().getSimpleName(), "Unable to get caller identity \n" + re); - } + mCallingUid = getLaunchedFromUid(); if (!UserHandle.isSameApp(mCallingUid, Process.SYSTEM_UID) && mCallingUid != mUid) { setResult(Activity.RESULT_CANCELED); diff --git a/core/java/android/animation/OWNERS b/core/java/android/animation/OWNERS new file mode 100644 index 000000000000..822a35c348ed --- /dev/null +++ b/core/java/android/animation/OWNERS @@ -0,0 +1,6 @@ +# Bug component: 47085 + +romainguy@google.com +tianliu@google.com +alanv@google.com +adamp@google.com diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index f92768a28db1..d8cb7a68753b 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -6230,6 +6230,23 @@ public class Activity extends ContextThemeWrapper } /** + * Returns the uid who started this activity. + * @hide + */ + public int getLaunchedFromUid() { + return ActivityClient.getInstance().getLaunchedFromUid(getActivityToken()); + } + + /** + * Returns the package who started this activity. + * @hide + */ + @Nullable + public String getLaunchedFromPackage() { + return ActivityClient.getInstance().getLaunchedFromPackage(getActivityToken()); + } + + /** * Control whether this activity's main window is visible. This is intended * only for the special case of an activity that is not going to show a * UI itself, but can't just finish prior to onResume() because it needs diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java index 84ecd24b8c55..64d795c013c9 100644 --- a/core/java/android/app/ActivityClient.java +++ b/core/java/android/app/ActivityClient.java @@ -221,6 +221,22 @@ public class ActivityClient { } } + public int getLaunchedFromUid(IBinder token) { + try { + return getActivityClientController().getLaunchedFromUid(token); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + public String getLaunchedFromPackage(IBinder token) { + try { + return getActivityClientController().getLaunchedFromPackage(token); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + Bundle getActivityOptions(IBinder token) { try { return getActivityClientController().getActivityOptions(token); @@ -451,8 +467,20 @@ public class ActivityClient { return sInstance.get(); } + /** + * If system server has passed the controller interface, store it so the subsequent access can + * speed up. + */ + public static IActivityClientController setActivityClientController( + IActivityClientController activityClientController) { + // No lock because it is no harm to encounter race condition. The thread safe Singleton#get + // will take over that case. + return INTERFACE_SINGLETON.mKnownInstance = activityClientController; + } + private static IActivityClientController getActivityClientController() { - return sActivityClientController.get(); + final IActivityClientController controller = INTERFACE_SINGLETON.mKnownInstance; + return controller != null ? controller : INTERFACE_SINGLETON.get(); } private static final Singleton<ActivityClient> sInstance = new Singleton<ActivityClient>() { @@ -462,8 +490,17 @@ public class ActivityClient { } }; - private static final Singleton<IActivityClientController> sActivityClientController = - new Singleton<IActivityClientController>() { + private static final ActivityClientControllerSingleton INTERFACE_SINGLETON = + new ActivityClientControllerSingleton(); + + private static class ActivityClientControllerSingleton + extends Singleton<IActivityClientController> { + /** + * A quick look up to reduce potential extra binder transactions. E.g. getting activity + * task manager from service manager and controller from activity task manager. + */ + IActivityClientController mKnownInstance; + @Override protected IActivityClientController create() { try { @@ -472,5 +509,5 @@ public class ActivityClient { throw e.rethrowFromSystemServer(); } } - }; + } } diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 38a22d8ade94..7af96d660f54 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -4167,10 +4167,8 @@ public class ActivityManager { "android.permission.INTERACT_ACROSS_USERS_FULL" }) public static int getCurrentUser() { - UserInfo ui; try { - ui = getService().getCurrentUser(); - return ui != null ? ui.id : 0; + return getService().getCurrentUserId(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 4dd6a7efe7c5..f60f569be892 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -1166,8 +1166,12 @@ public class AppOpsManager { public static final int OP_MANAGE_CREDENTIALS = AppProtoEnums.APP_OP_MANAGE_CREDENTIALS; /** @hide */ + public static final int OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER = + AppProtoEnums.APP_OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER; + + /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static final int _NUM_OP = 105; + public static final int _NUM_OP = 106; /** Access to coarse location information. */ public static final String OPSTR_COARSE_LOCATION = "android:coarse_location"; @@ -1525,6 +1529,15 @@ public class AppOpsManager { */ public static final String OPSTR_MANAGE_CREDENTIALS = "android:manage_credentials"; + /** + * Allows to read device identifiers and use ICC based authentication like EAP-AKA. + * + * @hide + */ + @TestApi + public static final String OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER = + "android:use_icc_auth_with_device_identifier"; + /** {@link #sAppOpsToNote} not initialized yet for this op */ private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0; /** Should not collect noting of this app-op in {@link #sAppOpsToNote} */ @@ -1604,6 +1617,7 @@ public class AppOpsManager { OP_INTERACT_ACROSS_PROFILES, OP_LOADER_USAGE_STATS, OP_MANAGE_ONGOING_CALLS, + OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, }; /** @@ -1720,6 +1734,7 @@ public class AppOpsManager { OP_RECORD_AUDIO_HOTWORD, // RECORD_AUDIO_HOTWORD OP_MANAGE_ONGOING_CALLS, // MANAGE_ONGOING_CALLS OP_MANAGE_CREDENTIALS, // MANAGE_CREDENTIALS + OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER }; /** @@ -1831,6 +1846,7 @@ public class AppOpsManager { OPSTR_RECORD_AUDIO_HOTWORD, OPSTR_MANAGE_ONGOING_CALLS, OPSTR_MANAGE_CREDENTIALS, + OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, }; /** @@ -1943,6 +1959,7 @@ public class AppOpsManager { "RECORD_AUDIO_HOTWORD", "MANAGE_ONGOING_CALLS", "MANAGE_CREDENTIALS", + "USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER", }; /** @@ -2056,6 +2073,7 @@ public class AppOpsManager { null, // no permission for OP_RECORD_AUDIO_HOTWORD Manifest.permission.MANAGE_ONGOING_CALLS, null, // no permission for OP_MANAGE_CREDENTIALS + Manifest.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, }; /** @@ -2169,6 +2187,7 @@ public class AppOpsManager { null, // RECORD_AUDIO_HOTWORD null, // MANAGE_ONGOING_CALLS null, // MANAGE_CREDENTIALS + null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER }; /** @@ -2281,6 +2300,7 @@ public class AppOpsManager { null, // RECORD_AUDIO_HOTWORD null, // MANAGE_ONGOING_CALLS null, // MANAGE_CREDENTIALS + null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER }; /** @@ -2392,6 +2412,7 @@ public class AppOpsManager { AppOpsManager.MODE_ALLOWED, // OP_RECORD_AUDIO_HOTWORD AppOpsManager.MODE_DEFAULT, // MANAGE_ONGOING_CALLS AppOpsManager.MODE_DEFAULT, // MANAGE_CREDENTIALS + AppOpsManager.MODE_DEFAULT, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER }; /** @@ -2507,6 +2528,7 @@ public class AppOpsManager { false, // RECORD_AUDIO_HOTWORD true, // MANAGE_ONGOING_CALLS false, // MANAGE_CREDENTIALS + true, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER }; /** diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java index 298c45582174..a16f6a84f18f 100644 --- a/core/java/android/app/BroadcastOptions.java +++ b/core/java/android/app/BroadcastOptions.java @@ -16,11 +16,15 @@ package android.app; +import android.annotation.IntDef; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.os.Build; import android.os.Bundle; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Helper class for building an options Bundle that can be used with * {@link android.content.Context#sendBroadcast(android.content.Intent) @@ -30,6 +34,7 @@ import android.os.Bundle; @SystemApi public class BroadcastOptions { private long mTemporaryAppWhitelistDuration; + private @TempAllowListType int mTemporaryAppWhitelistType; private int mMinManifestReceiverApiLevel = 0; private int mMaxManifestReceiverApiLevel = Build.VERSION_CODES.CUR_DEVELOPMENT; private boolean mDontSendToRestrictedApps = false; @@ -42,6 +47,9 @@ public class BroadcastOptions { static final String KEY_TEMPORARY_APP_WHITELIST_DURATION = "android:broadcast.temporaryAppWhitelistDuration"; + static final String KEY_TEMPORARY_APP_WHITELIST_TYPE + = "android:broadcast.temporaryAppWhitelistType"; + /** * Corresponds to {@link #setMinManifestReceiverApiLevel}. */ @@ -66,6 +74,27 @@ public class BroadcastOptions { static final String KEY_ALLOW_BACKGROUND_ACTIVITY_STARTS = "android:broadcast.allowBackgroundActivityStarts"; + /** + * Allow the temp allowlist behavior, plus allow foreground service start from background. + */ + public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 0; + /** + * Only allow the temp allowlist behavior, not allow foreground service start from + * background. + */ + public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED = 1; + + /** + * The list of temp allowlist types. + * @hide + */ + @IntDef(flag = true, prefix = { "TEMPORARY_WHITELIST_TYPE_" }, value = { + TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED, + TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface TempAllowListType {} + public static BroadcastOptions makeBasic() { BroadcastOptions opts = new BroadcastOptions(); return opts; @@ -77,6 +106,7 @@ public class BroadcastOptions { /** @hide */ public BroadcastOptions(Bundle opts) { mTemporaryAppWhitelistDuration = opts.getLong(KEY_TEMPORARY_APP_WHITELIST_DURATION); + mTemporaryAppWhitelistType = opts.getInt(KEY_TEMPORARY_APP_WHITELIST_TYPE); mMinManifestReceiverApiLevel = opts.getInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, 0); mMaxManifestReceiverApiLevel = opts.getInt(KEY_MAX_MANIFEST_RECEIVER_API_LEVEL, Build.VERSION_CODES.CUR_DEVELOPMENT); @@ -95,6 +125,22 @@ public class BroadcastOptions { android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppWhitelistDuration(long duration) { mTemporaryAppWhitelistDuration = duration; + mTemporaryAppWhitelistType = TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED; + } + + /** + * Set a duration for which the system should temporary place an application on the + * power allowlist when this broadcast is being delivered to it, specify the temp allowlist + * type. + * @param type one of {@link TempAllowListType} + * @param duration the duration in milliseconds; 0 means to not place on allowlist. + */ + @RequiresPermission(anyOf = {android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, + android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, + android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) + public void setTemporaryAppWhitelistDuration(@TempAllowListType int type, long duration) { + mTemporaryAppWhitelistDuration = duration; + mTemporaryAppWhitelistType = type; } /** @@ -106,6 +152,14 @@ public class BroadcastOptions { } /** + * Return {@link #mTemporaryAppWhitelistType}. + * @hide + */ + public @TempAllowListType int getTemporaryAppWhitelistType() { + return mTemporaryAppWhitelistType; + } + + /** * Set the minimum target API level of receivers of the broadcast. If an application * is targeting an API level less than this, the broadcast will not be delivered to * them. This only applies to receivers declared in the app's AndroidManifest.xml. @@ -190,6 +244,9 @@ public class BroadcastOptions { if (mTemporaryAppWhitelistDuration > 0) { b.putLong(KEY_TEMPORARY_APP_WHITELIST_DURATION, mTemporaryAppWhitelistDuration); } + if (mTemporaryAppWhitelistType != 0) { + b.putInt(KEY_TEMPORARY_APP_WHITELIST_TYPE, mTemporaryAppWhitelistType); + } if (mMinManifestReceiverApiLevel != 0) { b.putInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, mMinManifestReceiverApiLevel); } diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl index f9449f241545..e1e0a8a534a8 100644 --- a/core/java/android/app/IActivityClientController.aidl +++ b/core/java/android/app/IActivityClientController.aidl @@ -58,6 +58,8 @@ interface IActivityClientController { int getTaskForActivity(in IBinder token, in boolean onlyRoot); ComponentName getCallingActivity(in IBinder token); String getCallingPackage(in IBinder token); + int getLaunchedFromUid(in IBinder token); + String getLaunchedFromPackage(in IBinder token); Bundle getActivityOptions(in IBinder token); void setRequestedOrientation(in IBinder token, int requestedOrientation); diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 86625d340a14..c564d285fbc2 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -363,6 +363,7 @@ interface IActivityManager { boolean killProcessesBelowForeground(in String reason); @UnsupportedAppUsage UserInfo getCurrentUser(); + int getCurrentUserId(); // This is not public because you need to be very careful in how you // manage your activity to make sure it is always the uid you expect. @UnsupportedAppUsage diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl index 4b2557389382..fabce459afcc 100644 --- a/core/java/android/app/IActivityTaskManager.aidl +++ b/core/java/android/app/IActivityTaskManager.aidl @@ -159,8 +159,6 @@ interface IActivityTaskManager { int userId); boolean isTopActivityImmersive(); ActivityManager.TaskDescription getTaskDescription(int taskId); - int getLaunchedFromUid(in IBinder activityToken); - String getLaunchedFromPackage(in IBinder activityToken); void reportAssistContextExtras(in IBinder assistToken, in Bundle extras, in AssistStructure structure, in AssistContent content, in Uri referrer); @@ -257,8 +255,6 @@ interface IActivityTaskManager { * etc. */ void keyguardGoingAway(int flags); - ComponentName getActivityClassForToken(in IBinder token); - String getPackageForToken(in IBinder token); void suppressResizeConfigChanges(boolean suppress); boolean moveTopActivityToPinnedRootTask(int rootTaskId, in Rect bounds); diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 12460ba2bd4b..da7a29f8ac10 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -1501,7 +1501,8 @@ public class NotificationManager { } /** @hide */ - public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) { + @TestApi + public boolean isNotificationPolicyAccessGrantedForPackage(@NonNull String pkg) { INotificationManager service = getService(); try { return service.isNotificationPolicyAccessGrantedForPackage(pkg); diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS new file mode 100644 index 000000000000..633d093435ee --- /dev/null +++ b/core/java/android/app/OWNERS @@ -0,0 +1 @@ +per-file *Zygote* = file:/ZYGOTE_OWNERS diff --git a/core/java/android/app/PictureInPictureParams.java b/core/java/android/app/PictureInPictureParams.java index 32252a3f4bae..ea7eab2a2877 100644 --- a/core/java/android/app/PictureInPictureParams.java +++ b/core/java/android/app/PictureInPictureParams.java @@ -26,6 +26,7 @@ import android.util.Rational; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * Represents a set of parameters used to initialize and update an Activity in picture-in-picture @@ -47,7 +48,9 @@ public final class PictureInPictureParams implements Parcelable { @Nullable private Rect mSourceRectHint; - private boolean mAutoEnterEnabled; + private Boolean mAutoEnterEnabled; + + private Boolean mSeamlessResizeEnabled; /** * Sets the aspect ratio. This aspect ratio is defined as the desired width / height, and @@ -112,7 +115,7 @@ public final class PictureInPictureParams implements Parcelable { * * If true, {@link Activity#onPictureInPictureRequested()} will never be called. * - * This property is false by default. + * This property is {@code false} by default. * @param autoEnterEnabled {@code true} if the system will automatically put the activity * in picture-in-picture mode. * @@ -125,6 +128,23 @@ public final class PictureInPictureParams implements Parcelable { } /** + * Sets whether the system can seamlessly resize the window while the activity is in + * picture-in-picture mode. This should normally be the case for video content and + * when it's set to {@code false}, system will perform transitions to overcome the + * artifacts due to resize. + * + * This property is {@code true} by default for backwards compatibility. + * @param seamlessResizeEnabled {@code true} if the system can seamlessly resize the window + * while activity is in picture-in-picture mode. + * @return this builder instance. + */ + @NonNull + public Builder setSeamlessResizeEnabled(boolean seamlessResizeEnabled) { + mSeamlessResizeEnabled = seamlessResizeEnabled; + return this; + } + + /** * @return an immutable {@link PictureInPictureParams} to be used when entering or updating * the activity in picture-in-picture. * @@ -133,7 +153,7 @@ public final class PictureInPictureParams implements Parcelable { */ public PictureInPictureParams build() { PictureInPictureParams params = new PictureInPictureParams(mAspectRatio, mUserActions, - mSourceRectHint, mAutoEnterEnabled); + mSourceRectHint, mAutoEnterEnabled, mSeamlessResizeEnabled); return params; } } @@ -160,8 +180,16 @@ public final class PictureInPictureParams implements Parcelable { /** * Whether the system is allowed to automatically put the activity in picture-in-picture mode. + * {@link #isAutoEnterEnabled()} defaults to {@code false} if this is not set. */ - private boolean mAutoEnterEnabled; + private Boolean mAutoEnterEnabled; + + /** + * Whether system can seamlessly resize the window when activity is in picture-in-picture mode. + * {@link #isSeamlessResizeEnabled()} defaults to {@code true} if this is not set for + * backwards compatibility. + */ + private Boolean mSeamlessResizeEnabled; /** {@hide} */ PictureInPictureParams() { @@ -182,15 +210,29 @@ public final class PictureInPictureParams implements Parcelable { if (in.readInt() != 0) { mAutoEnterEnabled = in.readBoolean(); } + if (in.readInt() != 0) { + mSeamlessResizeEnabled = in.readBoolean(); + } } /** {@hide} */ PictureInPictureParams(Rational aspectRatio, List<RemoteAction> actions, - Rect sourceRectHint, boolean autoEnterEnabled) { + Rect sourceRectHint, Boolean autoEnterEnabled, Boolean seamlessResizeEnabled) { mAspectRatio = aspectRatio; mUserActions = actions; mSourceRectHint = sourceRectHint; mAutoEnterEnabled = autoEnterEnabled; + mSeamlessResizeEnabled = seamlessResizeEnabled; + } + + /** + * Makes a copy from the other picture-in-picture args. + * @hide + */ + public PictureInPictureParams(PictureInPictureParams other) { + this(other.mAspectRatio, other.mUserActions, + other.hasSourceBoundsHint() ? new Rect(other.getSourceRectHint()) : null, + other.mAutoEnterEnabled, other.mSeamlessResizeEnabled); } /** @@ -207,7 +249,12 @@ public final class PictureInPictureParams implements Parcelable { if (otherArgs.hasSourceBoundsHint()) { mSourceRectHint = new Rect(otherArgs.getSourceRectHint()); } - mAutoEnterEnabled = otherArgs.mAutoEnterEnabled; + if (otherArgs.mAutoEnterEnabled != null) { + mAutoEnterEnabled = otherArgs.mAutoEnterEnabled; + } + if (otherArgs.mSeamlessResizeEnabled != null) { + mSeamlessResizeEnabled = otherArgs.mSeamlessResizeEnabled; + } } /** @@ -284,7 +331,16 @@ public final class PictureInPictureParams implements Parcelable { * @hide */ public boolean isAutoEnterEnabled() { - return mAutoEnterEnabled; + return mAutoEnterEnabled == null ? false : mAutoEnterEnabled; + } + + /** + * @return whether seamless resize is enabled. + * @hide + */ + @TestApi + public boolean isSeamlessResizeEnabled() { + return mSeamlessResizeEnabled == null ? true : mSeamlessResizeEnabled; } /** @@ -293,7 +349,25 @@ public final class PictureInPictureParams implements Parcelable { */ public boolean empty() { return !hasSourceBoundsHint() && !hasSetActions() && !hasSetAspectRatio() - && !mAutoEnterEnabled; + && mAutoEnterEnabled != null && mSeamlessResizeEnabled != null; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof PictureInPictureParams)) return false; + PictureInPictureParams that = (PictureInPictureParams) o; + return Objects.equals(mAutoEnterEnabled, that.mAutoEnterEnabled) + && Objects.equals(mSeamlessResizeEnabled, that.mSeamlessResizeEnabled) + && Objects.equals(mAspectRatio, that.mAspectRatio) + && Objects.equals(mUserActions, that.mUserActions) + && Objects.equals(mSourceRectHint, that.mSourceRectHint); + } + + @Override + public int hashCode() { + return Objects.hash(mAspectRatio, mUserActions, mSourceRectHint, + mAutoEnterEnabled, mSeamlessResizeEnabled); } @Override @@ -322,8 +396,18 @@ public final class PictureInPictureParams implements Parcelable { } else { out.writeInt(0); } - out.writeInt(1); - out.writeBoolean(mAutoEnterEnabled); + if (mAutoEnterEnabled != null) { + out.writeInt(1); + out.writeBoolean(mAutoEnterEnabled); + } else { + out.writeInt(0); + } + if (mSeamlessResizeEnabled != null) { + out.writeInt(1); + out.writeBoolean(mSeamlessResizeEnabled); + } else { + out.writeInt(0); + } } @Override @@ -333,6 +417,7 @@ public final class PictureInPictureParams implements Parcelable { + " sourceRectHint=" + getSourceRectHint() + " hasSetActions=" + hasSetActions() + " isAutoPipEnabled=" + isAutoEnterEnabled() + + " isSeamlessResizeEnabled=" + isSeamlessResizeEnabled() + ")"; } diff --git a/core/java/android/app/RemoteAction.java b/core/java/android/app/RemoteAction.java index 5a4244f86ca3..26f324b57849 100644 --- a/core/java/android/app/RemoteAction.java +++ b/core/java/android/app/RemoteAction.java @@ -23,6 +23,7 @@ import android.os.Parcelable; import android.text.TextUtils; import java.io.PrintWriter; +import java.util.Objects; /** * Represents a remote action that can be called from another process. The action can have an @@ -127,6 +128,25 @@ public final class RemoteAction implements Parcelable { } @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof RemoteAction)) return false; + RemoteAction that = (RemoteAction) o; + return mEnabled == that.mEnabled + && mShouldShowIcon == that.mShouldShowIcon + && mIcon.equals(that.mIcon) + && mTitle.equals(that.mTitle) + && mContentDescription.equals(that.mContentDescription) + && mActionIntent.equals(that.mActionIntent); + } + + @Override + public int hashCode() { + return Objects.hash(mIcon, mTitle, mContentDescription, mActionIntent, mEnabled, + mShouldShowIcon); + } + + @Override public int describeContents() { return 0; } diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java index 1a8a4b7f16da..fe382a33a8c5 100644 --- a/core/java/android/app/TaskInfo.java +++ b/core/java/android/app/TaskInfo.java @@ -195,6 +195,14 @@ public class TaskInfo { public Rect letterboxActivityBounds; /** + * Activity insets if this task or its top activity is presented in letterbox mode and + * {@code null} otherwise. + * @hide + */ + @Nullable + public Rect letterboxActivityInsets; + + /** * Relative position of the task's top left corner in the parent container. * @hide */ @@ -313,7 +321,7 @@ public class TaskInfo { && isResizeable == that.isResizeable && Objects.equals(positionInParent, that.positionInParent) && equalsLetterboxParams(that) - && pictureInPictureParams == that.pictureInPictureParams + && Objects.equals(pictureInPictureParams, that.pictureInPictureParams) && getWindowingMode() == that.getWindowingMode() && Objects.equals(taskDescription, that.taskDescription) && isFocused == that.isFocused @@ -328,7 +336,8 @@ public class TaskInfo { && Objects.equals( getConfiguration().windowConfiguration.getMaxBounds(), that.getConfiguration().windowConfiguration.getMaxBounds()) - && Objects.equals(parentBounds, that.parentBounds); + && Objects.equals(parentBounds, that.parentBounds) + && Objects.equals(letterboxActivityInsets, that.letterboxActivityInsets); } /** @@ -365,6 +374,7 @@ public class TaskInfo { parentBounds = source.readTypedObject(Rect.CREATOR); isFocused = source.readBoolean(); isVisible = source.readBoolean(); + letterboxActivityInsets = source.readTypedObject(Rect.CREATOR); } /** @@ -402,6 +412,7 @@ public class TaskInfo { dest.writeTypedObject(parentBounds, flags); dest.writeBoolean(isFocused); dest.writeBoolean(isVisible); + dest.writeTypedObject(letterboxActivityInsets, flags); } @Override @@ -428,6 +439,7 @@ public class TaskInfo { + " parentBounds=" + parentBounds + " isFocused=" + isFocused + " isVisible=" + isVisible + + " letterboxActivityInsets=" + letterboxActivityInsets + "}"; } } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 4095acc239e9..ab94fd5922bc 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -2610,6 +2610,9 @@ public class DevicePolicyManager { /** @hide */ @TestApi public static final int OPERATION_REMOVE_USER = 6; + /** @hide */ + @TestApi + public static final int OPERATION_REBOOT = 7; private static final String PREFIX_OPERATION = "OPERATION_"; @@ -2620,7 +2623,8 @@ public class DevicePolicyManager { OPERATION_START_USER_IN_BACKGROUND, OPERATION_STOP_USER, OPERATION_CREATE_AND_MANAGE_USER, - OPERATION_REMOVE_USER + OPERATION_REMOVE_USER, + OPERATION_REBOOT }) @Retention(RetentionPolicy.SOURCE) public static @interface DevicePolicyOperation { @@ -5758,7 +5762,6 @@ public class DevicePolicyManager { return null; } - /** * Called by a device or profile owner, or delegated certificate chooser (an app that has been * delegated the {@link #DELEGATION_CERT_SELECTION} privilege), to grant an application access @@ -5796,6 +5799,51 @@ public class DevicePolicyManager { /** * Called by a device or profile owner, or delegated certificate chooser (an app that has been + * delegated the {@link #DELEGATION_CERT_SELECTION} privilege), to query which apps have access + * to a given KeyChain key. + * + * Key are granted on a per-UID basis, so if several apps share the same UID, granting access to + * one of them automatically grants it to others. This method returns a set of sets of package + * names, where each internal set contains all packages sharing the same UID. Grantee packages + * that don't share UID with other packages are represented by singleton sets. + * + * @param alias The alias of the key to grant access to. + * @return package names of apps that have access to a given key, grouped by UIDs + * + * @throws SecurityException if the caller is not a device owner, a profile owner or + * delegated certificate chooser. + * @throws IllegalArgumentException if {@code alias} doesn't correspond to an existing key. + * + * @see #grantKeyPairToApp(ComponentName, String, String) + */ + public @NonNull Set<Set<String>> getKeyPairGrants(@NonNull String alias) { + throwIfParentInstance("getKeyPairGrants"); + try { + // Set of sets is flattened into a null-separated list. + final List<String> flattened = + mService.getKeyPairGrants(mContext.getPackageName(), alias); + final Set<Set<String>> result = new HashSet<>(); + Set<String> pkgsForOneUid = new HashSet<>(); + for (final String pkg : flattened) { + if (pkg == null) { + result.add(pkgsForOneUid); + pkgsForOneUid = new HashSet<>(); + } else { + pkgsForOneUid.add(pkg); + } + } + if (!pkgsForOneUid.isEmpty()) { + result.add(pkgsForOneUid); + } + return result; + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + return null; + } + + /** + * Called by a device or profile owner, or delegated certificate chooser (an app that has been * delegated the {@link #DELEGATION_CERT_SELECTION} privilege), to revoke an application's * grant to a KeyChain key pair. * Calls by the application to {@link android.security.KeyChain#getPrivateKey} diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index e21fee2c5425..bcc90f79d629 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -471,6 +471,7 @@ interface IDevicePolicyManager { boolean startViewCalendarEventInManagedProfile(String packageName, long eventId, long start, long end, boolean allDay, int flags); boolean setKeyGrantForApp(in ComponentName admin, String callerPackage, String alias, String packageName, boolean hasGrant); + List<String> getKeyPairGrants(in String callerPackage, in String alias); void setUserControlDisabledPackages(in ComponentName admin, in List<String> packages); diff --git a/core/java/android/app/admin/OWNERS b/core/java/android/app/admin/OWNERS new file mode 100644 index 000000000000..64a1d27d4cf7 --- /dev/null +++ b/core/java/android/app/admin/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 142675 + +yamasani@google.com +rubinxu@google.com diff --git a/core/java/android/app/assist/OWNERS b/core/java/android/app/assist/OWNERS new file mode 100644 index 000000000000..46b5ea03c545 --- /dev/null +++ b/core/java/android/app/assist/OWNERS @@ -0,0 +1,7 @@ +joannechung@google.com +adamhe@google.com +tymtsai@google.com +lpeter@google.com +augale@google.com +svetoslavganov@android.com +svetoslavganov@google.com diff --git a/core/java/android/app/contentsuggestions/OWNERS b/core/java/android/app/contentsuggestions/OWNERS new file mode 100644 index 000000000000..482abb2d94e9 --- /dev/null +++ b/core/java/android/app/contentsuggestions/OWNERS @@ -0,0 +1,9 @@ +# Bug component: 643919 + +joannechung@google.com +adamhe@google.com +tymtsai@google.com +lpeter@google.com +augale@google.com +svetoslavganov@android.com +svetoslavganov@google.com diff --git a/core/java/android/app/prediction/OWNERS b/core/java/android/app/prediction/OWNERS new file mode 100644 index 000000000000..fe012da8e307 --- /dev/null +++ b/core/java/android/app/prediction/OWNERS @@ -0,0 +1,2 @@ +adamcohen@google.com +sunnygoyal@google.com diff --git a/core/java/android/app/role/OWNERS b/core/java/android/app/role/OWNERS index b94d98827d71..b807636658eb 100644 --- a/core/java/android/app/role/OWNERS +++ b/core/java/android/app/role/OWNERS @@ -1,6 +1,4 @@ -svetoslavganov@google.com -moltmann@google.com +# Bug component: 137825 + zhanghai@google.com -evanseverson@google.com -eugenesusla@google.com -ntmyren@google.com +moltmann@google.com diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java index 7f08bfbef289..3758cb49e2d0 100644 --- a/core/java/android/app/servertransaction/LaunchActivityItem.java +++ b/core/java/android/app/servertransaction/LaunchActivityItem.java @@ -20,8 +20,10 @@ import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.ActivityClient; import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; +import android.app.IActivityClientController; import android.app.ProfilerInfo; import android.app.ResultInfo; import android.compat.annotation.UnsupportedAppUsage; @@ -67,6 +69,11 @@ public class LaunchActivityItem extends ClientTransactionItem { private boolean mIsForward; private ProfilerInfo mProfilerInfo; private IBinder mAssistToken; + /** + * It is only non-null if the process is the first time to launch activity. It is only an + * optimization for quick look up of the interface so the field is ignored for comparison. + */ + private IActivityClientController mActivityClientController; private FixedRotationAdjustments mFixedRotationAdjustments; @Override @@ -74,6 +81,9 @@ public class LaunchActivityItem extends ClientTransactionItem { client.countLaunchingActivities(1); client.updateProcessState(mProcState, false); client.updatePendingConfiguration(mCurConfig); + if (mActivityClientController != null) { + ActivityClient.setActivityClientController(mActivityClientController); + } } @Override @@ -105,14 +115,16 @@ public class LaunchActivityItem extends ClientTransactionItem { String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean isForward, ProfilerInfo profilerInfo, - IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments) { + IBinder assistToken, IActivityClientController activityClientController, + FixedRotationAdjustments fixedRotationAdjustments) { LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class); if (instance == null) { instance = new LaunchActivityItem(); } setValues(instance, intent, ident, info, curConfig, overrideConfig, compatInfo, referrer, voiceInteractor, procState, state, persistentState, pendingResults, - pendingNewIntents, isForward, profilerInfo, assistToken, fixedRotationAdjustments); + pendingNewIntents, isForward, profilerInfo, assistToken, activityClientController, + fixedRotationAdjustments); return instance; } @@ -120,7 +132,7 @@ public class LaunchActivityItem extends ClientTransactionItem { @Override public void recycle() { setValues(this, null, 0, null, null, null, null, null, null, 0, null, null, null, null, - false, null, null, null); + false, null, null, null, null); ObjectPool.recycle(this); } @@ -146,6 +158,7 @@ public class LaunchActivityItem extends ClientTransactionItem { dest.writeBoolean(mIsForward); dest.writeTypedObject(mProfilerInfo, flags); dest.writeStrongBinder(mAssistToken); + dest.writeStrongInterface(mActivityClientController); dest.writeTypedObject(mFixedRotationAdjustments, flags); } @@ -162,6 +175,7 @@ public class LaunchActivityItem extends ClientTransactionItem { in.createTypedArrayList(ReferrerIntent.CREATOR), in.readBoolean(), in.readTypedObject(ProfilerInfo.CREATOR), in.readStrongBinder(), + IActivityClientController.Stub.asInterface(in.readStrongBinder()), in.readTypedObject(FixedRotationAdjustments.CREATOR)); } @@ -266,6 +280,7 @@ public class LaunchActivityItem extends ClientTransactionItem { int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken, + IActivityClientController activityClientController, FixedRotationAdjustments fixedRotationAdjustments) { instance.mIntent = intent; instance.mIdent = ident; @@ -283,6 +298,7 @@ public class LaunchActivityItem extends ClientTransactionItem { instance.mIsForward = isForward; instance.mProfilerInfo = profilerInfo; instance.mAssistToken = assistToken; + instance.mActivityClientController = activityClientController; instance.mFixedRotationAdjustments = fixedRotationAdjustments; } } diff --git a/core/java/android/app/servertransaction/OWNERS b/core/java/android/app/servertransaction/OWNERS new file mode 100644 index 000000000000..aa6248e7d826 --- /dev/null +++ b/core/java/android/app/servertransaction/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 316125 + +include /services/core/java/com/android/server/wm/OWNERS diff --git a/core/java/android/app/slice/OWNERS b/core/java/android/app/slice/OWNERS new file mode 100644 index 000000000000..b0a44fbeb4f9 --- /dev/null +++ b/core/java/android/app/slice/OWNERS @@ -0,0 +1,6 @@ +# Bug component: 342804 + +sunnygoyal@google.com +dsandler@android.com +dsandler@google.com +adamcohen@google.com diff --git a/core/java/android/app/timedetector/OWNERS b/core/java/android/app/timedetector/OWNERS new file mode 100644 index 000000000000..8c113246b5d4 --- /dev/null +++ b/core/java/android/app/timedetector/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 847766 + +narayan@google.com +nfuller@google.com diff --git a/core/java/android/app/timezone/OWNERS b/core/java/android/app/timezone/OWNERS new file mode 100644 index 000000000000..8c113246b5d4 --- /dev/null +++ b/core/java/android/app/timezone/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 847766 + +narayan@google.com +nfuller@google.com diff --git a/core/java/android/app/usage/OWNERS b/core/java/android/app/usage/OWNERS new file mode 100644 index 000000000000..a33d0adaa9b6 --- /dev/null +++ b/core/java/android/app/usage/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 532296 + +yamasani@google.com +mwachens@google.com +varunshah@google.com diff --git a/core/java/android/attention/OWNERS b/core/java/android/attention/OWNERS new file mode 100644 index 000000000000..dd579b6eb6dc --- /dev/null +++ b/core/java/android/attention/OWNERS @@ -0,0 +1 @@ +asalo@google.com diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index c07cd52c581e..1713a0c158c3 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -3689,7 +3689,7 @@ public final class BluetoothAdapter { * * @hide */ - public abstract class BluetoothConnectionCallback { + public abstract static class BluetoothConnectionCallback { /** * Callback triggered when a bluetooth device (classic or BLE) is connected * @param device is the connected bluetooth device diff --git a/core/java/android/bluetooth/OWNERS b/core/java/android/bluetooth/OWNERS new file mode 100644 index 000000000000..3523ee0640ab --- /dev/null +++ b/core/java/android/bluetooth/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 27441 + +zachoverflow@google.com +siyuanh@google.com diff --git a/core/java/android/bluetooth/le/OWNERS b/core/java/android/bluetooth/le/OWNERS new file mode 100644 index 000000000000..3523ee0640ab --- /dev/null +++ b/core/java/android/bluetooth/le/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 27441 + +zachoverflow@google.com +siyuanh@google.com diff --git a/core/java/android/companion/Association.java b/core/java/android/companion/Association.java index 06a3f2f08bab..17bf11b3d4ef 100644 --- a/core/java/android/companion/Association.java +++ b/core/java/android/companion/Association.java @@ -37,6 +37,8 @@ public final class Association implements Parcelable { private final @UserIdInt int mUserId; private final @NonNull String mDeviceMacAddress; private final @NonNull String mPackageName; + private final @Nullable String mDeviceProfile; + private final boolean mKeepProfilePrivilegesWhenDeviceAway; /** @hide */ public int getUserId() { @@ -45,7 +47,7 @@ public final class Association implements Parcelable { - // Code below generated by codegen v1.0.15. + // Code below generated by codegen v1.0.21. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -67,7 +69,9 @@ public final class Association implements Parcelable { public Association( @UserIdInt int userId, @NonNull String deviceMacAddress, - @NonNull String packageName) { + @NonNull String packageName, + @Nullable String deviceProfile, + boolean keepProfilePrivilegesWhenDeviceAway) { this.mUserId = userId; com.android.internal.util.AnnotationValidations.validate( UserIdInt.class, null, mUserId); @@ -77,6 +81,8 @@ public final class Association implements Parcelable { this.mPackageName = packageName; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mPackageName); + this.mDeviceProfile = deviceProfile; + this.mKeepProfilePrivilegesWhenDeviceAway = keepProfilePrivilegesWhenDeviceAway; // onConstructed(); // You can define this method to get a callback } @@ -91,6 +97,16 @@ public final class Association implements Parcelable { return mPackageName; } + @DataClass.Generated.Member + public @Nullable String getDeviceProfile() { + return mDeviceProfile; + } + + @DataClass.Generated.Member + public boolean isKeepProfilePrivilegesWhenDeviceAway() { + return mKeepProfilePrivilegesWhenDeviceAway; + } + @Override @DataClass.Generated.Member public String toString() { @@ -100,7 +116,9 @@ public final class Association implements Parcelable { return "Association { " + "userId = " + mUserId + ", " + "deviceMacAddress = " + mDeviceMacAddress + ", " + - "packageName = " + mPackageName + + "packageName = " + mPackageName + ", " + + "deviceProfile = " + mDeviceProfile + ", " + + "keepProfilePrivilegesWhenDeviceAway = " + mKeepProfilePrivilegesWhenDeviceAway + " }"; } @@ -119,7 +137,9 @@ public final class Association implements Parcelable { return true && mUserId == that.mUserId && Objects.equals(mDeviceMacAddress, that.mDeviceMacAddress) - && Objects.equals(mPackageName, that.mPackageName); + && Objects.equals(mPackageName, that.mPackageName) + && Objects.equals(mDeviceProfile, that.mDeviceProfile) + && mKeepProfilePrivilegesWhenDeviceAway == that.mKeepProfilePrivilegesWhenDeviceAway; } @Override @@ -132,6 +152,8 @@ public final class Association implements Parcelable { _hash = 31 * _hash + mUserId; _hash = 31 * _hash + Objects.hashCode(mDeviceMacAddress); _hash = 31 * _hash + Objects.hashCode(mPackageName); + _hash = 31 * _hash + Objects.hashCode(mDeviceProfile); + _hash = 31 * _hash + Boolean.hashCode(mKeepProfilePrivilegesWhenDeviceAway); return _hash; } @@ -141,9 +163,14 @@ public final class Association implements Parcelable { // You can override field parcelling by defining methods like: // void parcelFieldName(Parcel dest, int flags) { ... } + byte flg = 0; + if (mKeepProfilePrivilegesWhenDeviceAway) flg |= 0x10; + if (mDeviceProfile != null) flg |= 0x8; + dest.writeByte(flg); dest.writeInt(mUserId); dest.writeString(mDeviceMacAddress); dest.writeString(mPackageName); + if (mDeviceProfile != null) dest.writeString(mDeviceProfile); } @Override @@ -157,9 +184,12 @@ public final class Association implements Parcelable { // You can override field unparcelling by defining methods like: // static FieldType unparcelFieldName(Parcel in) { ... } + byte flg = in.readByte(); + boolean keepProfilePrivilegesWhenDeviceAway = (flg & 0x10) != 0; int userId = in.readInt(); String deviceMacAddress = in.readString(); String packageName = in.readString(); + String deviceProfile = (flg & 0x8) == 0 ? null : in.readString(); this.mUserId = userId; com.android.internal.util.AnnotationValidations.validate( @@ -170,6 +200,8 @@ public final class Association implements Parcelable { this.mPackageName = packageName; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mPackageName); + this.mDeviceProfile = deviceProfile; + this.mKeepProfilePrivilegesWhenDeviceAway = keepProfilePrivilegesWhenDeviceAway; // onConstructed(); // You can define this method to get a callback } @@ -189,10 +221,10 @@ public final class Association implements Parcelable { }; @DataClass.Generated( - time = 1599083149942L, - codegenVersion = "1.0.15", + time = 1606940835778L, + codegenVersion = "1.0.21", sourceFile = "frameworks/base/core/java/android/companion/Association.java", - inputSignatures = "private final @android.annotation.UserIdInt int mUserId\nprivate final @android.annotation.NonNull java.lang.String mDeviceMacAddress\nprivate final @android.annotation.NonNull java.lang.String mPackageName\npublic int getUserId()\nclass Association extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstructor=true)") + inputSignatures = "private final @android.annotation.UserIdInt int mUserId\nprivate final @android.annotation.NonNull java.lang.String mDeviceMacAddress\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mDeviceProfile\nprivate final boolean mKeepProfilePrivilegesWhenDeviceAway\npublic int getUserId()\nclass Association extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstructor=true)") @Deprecated private void __metadata() {} diff --git a/core/java/android/content/om/OWNERS b/core/java/android/content/om/OWNERS new file mode 100644 index 000000000000..91a0abfe711a --- /dev/null +++ b/core/java/android/content/om/OWNERS @@ -0,0 +1,6 @@ +# Bug component: 568631 + +toddke@android.com +toddke@google.com +patb@google.com +rtmitchell@google.com diff --git a/core/java/android/content/pm/OWNERS b/core/java/android/content/pm/OWNERS index a16bb4ff3b1d..3a590dac7c0b 100644 --- a/core/java/android/content/pm/OWNERS +++ b/core/java/android/content/pm/OWNERS @@ -1 +1,7 @@ +# Bug component: 36137 + +toddke@android.com +toddke@google.com +patb@google.com + per-file PackageParser.java = chiuwinson@google.com diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index d4a98f82a4f7..4347f9988223 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -37,6 +37,7 @@ import android.content.Intent; import android.content.IntentSender; import android.content.pm.PackageManager.DeleteFlags; import android.content.pm.PackageManager.InstallReason; +import android.content.pm.PackageManager.InstallScenario; import android.graphics.Bitmap; import android.net.Uri; import android.os.Build; @@ -1525,6 +1526,14 @@ public class PackageInstaller { public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY; /** {@hide} */ public @InstallReason int installReason = PackageManager.INSTALL_REASON_UNKNOWN; + /** + * {@hide} + * + * This flag indicates which installation scenario best describes this session. The system + * may use this value when making decisions about how to handle the installation, such as + * prioritizing system health or user experience. + */ + public @InstallScenario int installScenario = PackageManager.INSTALL_SCENARIO_DEFAULT; /** {@hide} */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long sizeBytes = -1; @@ -1588,6 +1597,7 @@ public class PackageInstaller { installFlags = source.readInt(); installLocation = source.readInt(); installReason = source.readInt(); + installScenario = source.readInt(); sizeBytes = source.readLong(); appPackageName = source.readString(); appIcon = source.readParcelable(null); @@ -1619,6 +1629,7 @@ public class PackageInstaller { ret.installFlags = installFlags; ret.installLocation = installLocation; ret.installReason = installReason; + ret.installScenario = installScenario; ret.sizeBytes = sizeBytes; ret.appPackageName = appPackageName; ret.appIcon = appIcon; // not a copy. @@ -2044,6 +2055,8 @@ public class PackageInstaller { pw.printPair("mode", mode); pw.printHexPair("installFlags", installFlags); pw.printPair("installLocation", installLocation); + pw.printPair("installReason", installReason); + pw.printPair("installScenario", installScenario); pw.printPair("sizeBytes", sizeBytes); pw.printPair("appPackageName", appPackageName); pw.printPair("appIcon", (appIcon != null)); @@ -2077,6 +2090,7 @@ public class PackageInstaller { dest.writeInt(installFlags); dest.writeInt(installLocation); dest.writeInt(installReason); + dest.writeInt(installScenario); dest.writeLong(sizeBytes); dest.writeString(appPackageName); dest.writeParcelable(appIcon, flags); @@ -2195,6 +2209,8 @@ public class PackageInstaller { /** {@hide} */ public @InstallReason int installReason; /** {@hide} */ + public @InstallReason int installScenario; + /** {@hide} */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public long sizeBytes; /** {@hide} */ @@ -2273,6 +2289,7 @@ public class PackageInstaller { mode = source.readInt(); installReason = source.readInt(); + installScenario = source.readInt(); sizeBytes = source.readLong(); appPackageName = source.readString(); appIcon = source.readParcelable(null); @@ -2820,6 +2837,7 @@ public class PackageInstaller { dest.writeInt(mode); dest.writeInt(installReason); + dest.writeInt(installScenario); dest.writeLong(sizeBytes); dest.writeString(appPackageName); dest.writeParcelable(appIcon, flags); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index d550c7c68033..cf3f7069c63f 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1323,6 +1323,60 @@ public abstract class PackageManager { public static final int INSTALL_REASON_ROLLBACK = 5; /** @hide */ + @IntDef(prefix = { "INSTALL_SCENARIO_" }, value = { + INSTALL_SCENARIO_DEFAULT, + INSTALL_SCENARIO_FAST, + INSTALL_SCENARIO_BULK, + INSTALL_SCENARIO_BULK_SECONDARY, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface InstallScenario {} + + /** + * A value to indicate the lack of CUJ information, disabling all installation scenario logic. + * + * @hide + */ + public static final int INSTALL_SCENARIO_DEFAULT = 0; + + /** + * Installation scenario providing the fastest “install button to launch" experience possible. + * + * @hide + */ + public static final int INSTALL_SCENARIO_FAST = 1; + + /** + * Installation scenario indicating a bulk operation with the desired result of a fully + * optimized application. If the system is busy or resources are scarce the system will + * perform less work to avoid impacting system health. + * + * Examples of bulk installation scenarios might include device restore, background updates of + * multiple applications, or user-triggered updates for all applications. + * + * The decision to use BULK or BULK_SECONDARY should be based on the desired user experience. + * BULK_SECONDARY operations may take less time to complete but, when they do, will produce + * less optimized applications. The device state (e.g. memory usage or battery status) should + * not be considered when making this decision as those factors are taken into account by the + * Package Manager when acting on the installation scenario. + * + * @hide + */ + public static final int INSTALL_SCENARIO_BULK = 2; + + /** + * Installation scenario indicating a bulk operation that prioritizes minimal system health + * impact over application optimization. The application may undergo additional optimization + * if the system is idle and system resources are abundant. The more elements of a bulk + * operation that are marked BULK_SECONDARY, the faster the entire bulk operation will be. + * + * See the comments for INSTALL_SCENARIO_BULK for more information. + * + * @hide + */ + public static final int INSTALL_SCENARIO_BULK_SECONDARY = 3; + + /** @hide */ @IntDef(prefix = { "UNINSTALL_REASON_" }, value = { UNINSTALL_REASON_UNKNOWN, UNINSTALL_REASON_USER_TYPE, diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java index cd9ba6a5b451..35f02a8d5dd2 100644 --- a/core/java/android/content/pm/PermissionInfo.java +++ b/core/java/android/content/pm/PermissionInfo.java @@ -65,12 +65,20 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { @Deprecated public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3; + /** + * System-level value for {@link #protectionLevel}, corresponding + * to the <code>internal</code> value of + * {@link android.R.attr#protectionLevel}. + */ + public static final int PROTECTION_INTERNAL = 4; + /** @hide */ @IntDef(flag = false, prefix = { "PROTECTION_" }, value = { PROTECTION_NORMAL, PROTECTION_DANGEROUS, PROTECTION_SIGNATURE, PROTECTION_SIGNATURE_OR_SYSTEM, + PROTECTION_INTERNAL, }) @Retention(RetentionPolicy.SOURCE) public @interface Protection {} @@ -261,6 +269,15 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { @SystemApi public static final int PROTECTION_FLAG_RECENTS = 0x2000000; + /** + * Additional flag for {@link #protectionLevel}, corresponding to the <code>role</code> value of + * {@link android.R.attr#protectionLevel}. + * + * @hide + */ + @SystemApi + public static final int PROTECTION_FLAG_ROLE = 0x4000000; + /** @hide */ @IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = { PROTECTION_FLAG_PRIVILEGED, @@ -285,6 +302,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { PROTECTION_FLAG_COMPANION, PROTECTION_FLAG_RETAIL_DEMO, PROTECTION_FLAG_RECENTS, + PROTECTION_FLAG_ROLE, }) @Retention(RetentionPolicy.SOURCE) public @interface ProtectionFlags {} @@ -317,7 +335,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { * </pre> * * <p></p>Base permission types are {@link #PROTECTION_NORMAL}, - * {@link #PROTECTION_DANGEROUS}, {@link #PROTECTION_SIGNATURE} + * {@link #PROTECTION_DANGEROUS}, {@link #PROTECTION_SIGNATURE}, {@link #PROTECTION_INTERNAL} * and the deprecated {@link #PROTECTION_SIGNATURE_OR_SYSTEM}. * Flags are listed under {@link android.R.attr#protectionLevel}. * @@ -479,6 +497,9 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { case PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM: protLevel.append("signatureOrSystem"); break; + case PermissionInfo.PROTECTION_INTERNAL: + protLevel.append("internal"); + break; default: protLevel.append("????"); break; @@ -546,6 +567,9 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { if ((level & PermissionInfo.PROTECTION_FLAG_RECENTS) != 0) { protLevel.append("|recents"); } + if ((level & PermissionInfo.PROTECTION_FLAG_ROLE) != 0) { + protLevel.append("|role"); + } return protLevel.toString(); } diff --git a/core/java/android/content/pm/dex/OWNERS b/core/java/android/content/pm/dex/OWNERS new file mode 100644 index 000000000000..267e5d58f9a6 --- /dev/null +++ b/core/java/android/content/pm/dex/OWNERS @@ -0,0 +1,7 @@ +# Bug component: 86431 + +toddke@android.com +toddke@google.com +patb@google.com +calin@google.com +ngeoffray@google.com diff --git a/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java b/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java index 894849ada213..cbd2c550a797 100644 --- a/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java +++ b/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java @@ -112,10 +112,12 @@ public class ParsedPermissionUtils { if ((permission.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) == 0 && (permission.protectionLevel & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0 - && (permission.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) != - PermissionInfo.PROTECTION_SIGNATURE) { + && (permission.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) + != PermissionInfo.PROTECTION_SIGNATURE + && (permission.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) + != PermissionInfo.PROTECTION_INTERNAL) { return input.error("<permission> protectionLevel specifies a non-instant flag " - + "but is not based on signature type"); + + "but is not based on signature or internal type"); } } diff --git a/core/java/android/content/pm/permission/OWNERS b/core/java/android/content/pm/permission/OWNERS new file mode 100644 index 000000000000..cde7b2ac1898 --- /dev/null +++ b/core/java/android/content/pm/permission/OWNERS @@ -0,0 +1,11 @@ +# Bug component: 137825 + +toddke@android.com +toddke@google.com +patb@google.com +moltmann@google.com +svetoslavganov@android.com +svetoslavganov@google.com +zhanghai@google.com +evanseverson@google.com +ntmyren@google.com diff --git a/core/java/android/content/pm/split/OWNERS b/core/java/android/content/pm/split/OWNERS new file mode 100644 index 000000000000..3d126d297e60 --- /dev/null +++ b/core/java/android/content/pm/split/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 36137 + +toddke@android.com +toddke@google.com +patb@google.com diff --git a/core/java/android/content/res/OWNERS b/core/java/android/content/res/OWNERS new file mode 100644 index 000000000000..bc2355c6af5e --- /dev/null +++ b/core/java/android/content/res/OWNERS @@ -0,0 +1,6 @@ +# Bug component: 568761 + +toddke@android.com +toddke@google.com +patb@google.com +rtmitchell@google.com diff --git a/core/java/android/content/rollback/OWNERS b/core/java/android/content/rollback/OWNERS new file mode 100644 index 000000000000..3093fd686a21 --- /dev/null +++ b/core/java/android/content/rollback/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 557916 + +narayan@google.com +nandana@google.com +olilan@google.com diff --git a/core/java/android/database/OWNERS b/core/java/android/database/OWNERS index 7e19942ba332..1734cfcad360 100644 --- a/core/java/android/database/OWNERS +++ b/core/java/android/database/OWNERS @@ -1,3 +1,3 @@ omakoto@google.com -jsharkey@android.com +jsharkey@google.com yamasani@google.com diff --git a/core/java/android/gesture/OWNERS b/core/java/android/gesture/OWNERS new file mode 100644 index 000000000000..b3b8775dc036 --- /dev/null +++ b/core/java/android/gesture/OWNERS @@ -0,0 +1,8 @@ +# Bug component: 25700 + +romainguy@google.com +alanv@google.com +adamp@google.com +aurimas@google.com +nduca@google.com +sumir@google.com diff --git a/core/java/android/hardware/biometrics/OWNERS b/core/java/android/hardware/biometrics/OWNERS new file mode 100644 index 000000000000..33527f824827 --- /dev/null +++ b/core/java/android/hardware/biometrics/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 879035 + +jaggies@google.com diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index a0c12235dea9..0f595b700013 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -1467,12 +1467,13 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * to any real physical measurement, but <code>0.0f</code> still represents farthest * focus, and {@link CameraCharacteristics#LENS_INFO_MINIMUM_FOCUS_DISTANCE android.lens.info.minimumFocusDistance} represents the * nearest focus the device can achieve.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED UNCALIBRATED}</li> * <li>{@link #LENS_INFO_FOCUS_DISTANCE_CALIBRATION_APPROXIMATE APPROXIMATE}</li> * <li>{@link #LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED CALIBRATED}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * <p><b>Limited capability</b> - * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the @@ -1495,12 +1496,13 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri /** * <p>Direction the camera faces relative to * device screen.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #LENS_FACING_FRONT FRONT}</li> * <li>{@link #LENS_FACING_BACK BACK}</li> * <li>{@link #LENS_FACING_EXTERNAL EXTERNAL}</li> - * </ul></p> + * </ul> + * * <p>This key is available on all devices.</p> * @see #LENS_FACING_FRONT * @see #LENS_FACING_BACK @@ -1726,12 +1728,13 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation} and {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}.</p> * <p>Different calibration methods and use cases can produce better or worse results * depending on the selected coordinate origin.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #LENS_POSE_REFERENCE_PRIMARY_CAMERA PRIMARY_CAMERA}</li> * <li>{@link #LENS_POSE_REFERENCE_GYROSCOPE GYROSCOPE}</li> * <li>{@link #LENS_POSE_REFERENCE_UNDEFINED UNDEFINED}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p> * @@ -2057,7 +2060,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * </ul> * <p>Other capabilities may be available on either FULL or LIMITED * devices, but the application should query this key to be sure.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE BACKWARD_COMPATIBLE}</li> * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR MANUAL_SENSOR}</li> @@ -2075,7 +2078,8 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA SECURE_IMAGE_DATA}</li> * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA SYSTEM_CAMERA}</li> * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING OFFLINE_PROCESSING}</li> - * </ul></p> + * </ul> + * * <p>This key is available on all devices.</p> * * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL @@ -2777,11 +2781,12 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * array.</li> * </ul> * <p>LEGACY capability devices will only support CENTER_ONLY cropping.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #SCALER_CROPPING_TYPE_CENTER_ONLY CENTER_ONLY}</li> * <li>{@link #SCALER_CROPPING_TYPE_FREEFORM FREEFORM}</li> - * </ul></p> + * </ul> + * * <p>This key is available on all devices.</p> * * @see CaptureRequest#CONTROL_ZOOM_RATIO @@ -2966,7 +2971,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * represents the colors in the top-left 2x2 section of * the sensor, in reading order, for a Bayer camera, or the * light spectrum it captures for MONOCHROME camera.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB RGGB}</li> * <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG GRBG}</li> @@ -2975,7 +2980,8 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB RGB}</li> * <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO MONO}</li> * <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR NIR}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * <p><b>Full capability</b> - * Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the @@ -3117,11 +3123,12 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * may not based on a time source that can be compared to other system time sources.</p> * <p>This characteristic defines the source for the timestamps, and therefore whether they * can be compared against other system time sources/timestamps.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN UNKNOWN}</li> * <li>{@link #SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME REALTIME}</li> - * </ul></p> + * </ul> + * * <p>This key is available on all devices.</p> * @see #SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN * @see #SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME @@ -3231,7 +3238,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * {@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2 android.sensor.referenceIlluminant2} and its corresponding matrices.</p> * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if * the camera device has RAW capability.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT DAYLIGHT}</li> * <li>{@link #SENSOR_REFERENCE_ILLUMINANT1_FLUORESCENT FLUORESCENT}</li> @@ -3252,7 +3259,8 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <li>{@link #SENSOR_REFERENCE_ILLUMINANT1_D75 D75}</li> * <li>{@link #SENSOR_REFERENCE_ILLUMINANT1_D50 D50}</li> * <li>{@link #SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN ISO_STUDIO_TUNGSTEN}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p> * @@ -3727,10 +3735,11 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri /** * <p>A list of camera LEDs that are available on this system.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #LED_AVAILABLE_LEDS_TRANSMIT TRANSMIT}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * @see #LED_AVAILABLE_LEDS_TRANSMIT * @hide @@ -3799,14 +3808,15 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * ({@link CameraCharacteristics#LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION android.lens.info.availableOpticalStabilization}, * {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES android.control.availableVideoStabilizationModes})</li> * </ul> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}</li> * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}</li> * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}</li> * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_3 3}</li> * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL EXTERNAL}</li> - * </ul></p> + * </ul> + * * <p>This key is available on all devices.</p> * * @see CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES @@ -3850,11 +3860,12 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * must occur before the camera device knows for a fact that the new * submitted camera settings have been applied in outgoing frames.</p> * <p><b>Units</b>: Frame counts</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #SYNC_MAX_LATENCY_PER_FRAME_CONTROL PER_FRAME_CONTROL}</li> * <li>{@link #SYNC_MAX_LATENCY_UNKNOWN UNKNOWN}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * A positive value, PER_FRAME_CONTROL, or UNKNOWN.</p> * <p>This key is available on all devices.</p> @@ -4102,11 +4113,12 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * onCaptureStarted callback.</p> * <p>This tag is only applicable if the logical camera device supports concurrent physical * streams from different physical cameras.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_APPROXIMATE APPROXIMATE}</li> * <li>{@link #LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_CALIBRATED CALIBRATED}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * <p><b>Limited capability</b> - * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index 8469f5f981ed..cdfdc1fdb2c3 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -20,6 +20,7 @@ import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.content.Context; @@ -850,13 +851,17 @@ public final class CameraManager { * A camera device has been opened by an application. * * <p>The default implementation of this method does nothing.</p> - * - * @param cameraId The unique identifier of the new camera. + * android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER is required to receive this + * callback + * @param cameraId The unique identifier of the camera opened. * @param packageId The package Id of the application opening the camera. * * @see #onCameraClosed + * @hide */ - /** @hide */ + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraOpened(@NonNull String cameraId, @NonNull String packageId) { // default empty implementation } @@ -865,10 +870,14 @@ public final class CameraManager { * A previously-opened camera has been closed. * * <p>The default implementation of this method does nothing.</p> - * + * android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER is required to receive this + * callback. * @param cameraId The unique identifier of the closed camera. + * @hide */ - /** @hide */ + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraClosed(@NonNull String cameraId) { // default empty implementation } diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index d85bcbd15e50..d7aee10a5b93 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -1028,12 +1028,13 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * </code></pre> * <p>Both the input and output value ranges must match. Overflow/underflow * values are clipped to fit within the range.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #COLOR_CORRECTION_MODE_TRANSFORM_MATRIX TRANSFORM_MATRIX}</li> * <li>{@link #COLOR_CORRECTION_MODE_FAST FAST}</li> * <li>{@link #COLOR_CORRECTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * <p><b>Full capability</b> - * Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the @@ -1121,12 +1122,13 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * capture rate. FAST means the camera device will not slow down capture rate when * applying aberration correction.</p> * <p>LEGACY devices will always be in FAST mode.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #COLOR_CORRECTION_ABERRATION_MODE_OFF OFF}</li> * <li>{@link #COLOR_CORRECTION_ABERRATION_MODE_FAST FAST}</li> * <li>{@link #COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY HIGH_QUALITY}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES android.colorCorrection.availableAberrationModes}</p> * <p>This key is available on all devices.</p> @@ -1173,13 +1175,14 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * ensure it selects exposure times that do not cause banding * issues. The {@link CaptureResult#STATISTICS_SCENE_FLICKER android.statistics.sceneFlicker} key can assist * the application in this.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_AE_ANTIBANDING_MODE_OFF OFF}</li> * <li>{@link #CONTROL_AE_ANTIBANDING_MODE_50HZ 50HZ}</li> * <li>{@link #CONTROL_AE_ANTIBANDING_MODE_60HZ 60HZ}</li> * <li>{@link #CONTROL_AE_ANTIBANDING_MODE_AUTO AUTO}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br></p> * <p>{@link CameraCharacteristics#CONTROL_AE_AVAILABLE_ANTIBANDING_MODES android.control.aeAvailableAntibandingModes}</p> * <p>This key is available on all devices.</p> @@ -1304,7 +1307,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * camera device auto-exposure routine for the overridden * fields for a given capture will be available in its * CaptureResult.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_AE_MODE_OFF OFF}</li> * <li>{@link #CONTROL_AE_MODE_ON ON}</li> @@ -1312,7 +1315,8 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <li>{@link #CONTROL_AE_MODE_ON_ALWAYS_FLASH ON_ALWAYS_FLASH}</li> * <li>{@link #CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE ON_AUTO_FLASH_REDEYE}</li> * <li>{@link #CONTROL_AE_MODE_ON_EXTERNAL_FLASH ON_EXTERNAL_FLASH}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_MODES android.control.aeAvailableModes}</p> * <p>This key is available on all devices.</p> @@ -1478,12 +1482,13 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * example.</p> * <p>If both the precapture and the auto-focus trigger are activated on the same request, then * the camera device will complete them in the optimal order for that device.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE IDLE}</li> * <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_START START}</li> * <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL CANCEL}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * <p><b>Limited capability</b> - * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the @@ -1514,7 +1519,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <p>If the lens is controlled by the camera device auto-focus algorithm, * the camera device will report the current AF status in {@link CaptureResult#CONTROL_AF_STATE android.control.afState} * in result metadata.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_AF_MODE_OFF OFF}</li> * <li>{@link #CONTROL_AF_MODE_AUTO AUTO}</li> @@ -1522,7 +1527,8 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <li>{@link #CONTROL_AF_MODE_CONTINUOUS_VIDEO CONTINUOUS_VIDEO}</li> * <li>{@link #CONTROL_AF_MODE_CONTINUOUS_PICTURE CONTINUOUS_PICTURE}</li> * <li>{@link #CONTROL_AF_MODE_EDOF EDOF}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#CONTROL_AF_AVAILABLE_MODES android.control.afAvailableModes}</p> * <p>This key is available on all devices.</p> @@ -1637,12 +1643,13 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * focus sweep), the camera device may delay acting on a later trigger until the previous * trigger has been fully handled. This may lead to longer intervals between the trigger and * changes to {@link CaptureResult#CONTROL_AF_STATE android.control.afState}, for example.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_AF_TRIGGER_IDLE IDLE}</li> * <li>{@link #CONTROL_AF_TRIGGER_START START}</li> * <li>{@link #CONTROL_AF_TRIGGER_CANCEL CANCEL}</li> - * </ul></p> + * </ul> + * * <p>This key is available on all devices.</p> * * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER @@ -1710,7 +1717,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}, * {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} and * {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode} are ignored.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_AWB_MODE_OFF OFF}</li> * <li>{@link #CONTROL_AWB_MODE_AUTO AUTO}</li> @@ -1721,7 +1728,8 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <li>{@link #CONTROL_AWB_MODE_CLOUDY_DAYLIGHT CLOUDY_DAYLIGHT}</li> * <li>{@link #CONTROL_AWB_MODE_TWILIGHT TWILIGHT}</li> * <li>{@link #CONTROL_AWB_MODE_SHADE SHADE}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#CONTROL_AWB_AVAILABLE_MODES android.control.awbAvailableModes}</p> * <p>This key is available on all devices.</p> @@ -1835,7 +1843,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * MANUAL_SENSOR. * * MOTION_TRACKING will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains * MOTION_TRACKING.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_CAPTURE_INTENT_CUSTOM CUSTOM}</li> * <li>{@link #CONTROL_CAPTURE_INTENT_PREVIEW PREVIEW}</li> @@ -1845,7 +1853,8 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <li>{@link #CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG ZERO_SHUTTER_LAG}</li> * <li>{@link #CONTROL_CAPTURE_INTENT_MANUAL MANUAL}</li> * <li>{@link #CONTROL_CAPTURE_INTENT_MOTION_TRACKING MOTION_TRACKING}</li> - * </ul></p> + * </ul> + * * <p>This key is available on all devices.</p> * * @see CaptureRequest#CONTROL_MODE @@ -1872,7 +1881,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * implementor of the camera device, and should not be * depended on to be consistent (or present) across all * devices.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_EFFECT_MODE_OFF OFF}</li> * <li>{@link #CONTROL_EFFECT_MODE_MONO MONO}</li> @@ -1883,7 +1892,8 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <li>{@link #CONTROL_EFFECT_MODE_WHITEBOARD WHITEBOARD}</li> * <li>{@link #CONTROL_EFFECT_MODE_BLACKBOARD BLACKBOARD}</li> * <li>{@link #CONTROL_EFFECT_MODE_AQUA AQUA}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#CONTROL_AVAILABLE_EFFECTS android.control.availableEffects}</p> * <p>This key is available on all devices.</p> @@ -1922,14 +1932,15 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * update, as if this frame is never captured. This mode can be used in the scenario * where the application doesn't want a 3A manual control capture to affect * the subsequent auto 3A capture results.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_MODE_OFF OFF}</li> * <li>{@link #CONTROL_MODE_AUTO AUTO}</li> * <li>{@link #CONTROL_MODE_USE_SCENE_MODE USE_SCENE_MODE}</li> * <li>{@link #CONTROL_MODE_OFF_KEEP_STATE OFF_KEEP_STATE}</li> * <li>{@link #CONTROL_MODE_USE_EXTENDED_SCENE_MODE USE_EXTENDED_SCENE_MODE}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#CONTROL_AVAILABLE_MODES android.control.availableModes}</p> * <p>This key is available on all devices.</p> @@ -1959,7 +1970,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * to the implementor of the camera device. Their behavior will not be * consistent across all devices, and any given device may only implement * a subset of these modes.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_SCENE_MODE_DISABLED DISABLED}</li> * <li>{@link #CONTROL_SCENE_MODE_FACE_PRIORITY FACE_PRIORITY}</li> @@ -1980,7 +1991,8 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <li>{@link #CONTROL_SCENE_MODE_BARCODE BARCODE}</li> * <li>{@link #CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO}</li> * <li>{@link #CONTROL_SCENE_MODE_HDR HDR}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}</p> * <p>This key is available on all devices.</p> @@ -2041,11 +2053,12 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * ({@link CaptureRequest#LENS_OPTICAL_STABILIZATION_MODE android.lens.opticalStabilizationMode}), turning both modes on may * produce undesirable interaction, so it is recommended not to enable * both at the same time.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_VIDEO_STABILIZATION_MODE_OFF OFF}</li> * <li>{@link #CONTROL_VIDEO_STABILIZATION_MODE_ON ON}</li> - * </ul></p> + * </ul> + * * <p>This key is available on all devices.</p> * * @see CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE @@ -2155,12 +2168,13 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * with different field of view. As a result, when bokeh mode is enabled, the camera device * may override {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} or {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}, and the field of * view may be smaller than when bokeh mode is off.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_EXTENDED_SCENE_MODE_DISABLED DISABLED}</li> * <li>{@link #CONTROL_EXTENDED_SCENE_MODE_BOKEH_STILL_CAPTURE BOKEH_STILL_CAPTURE}</li> * <li>{@link #CONTROL_EXTENDED_SCENE_MODE_BOKEH_CONTINUOUS BOKEH_CONTINUOUS}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * * @see CaptureRequest#CONTROL_ZOOM_RATIO @@ -2287,13 +2301,14 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * device will apply FAST/HIGH_QUALITY YUV-domain edge enhancement, respectively. * The camera device may adjust its internal edge enhancement parameters for best * image quality based on the {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor}, if it is set.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #EDGE_MODE_OFF OFF}</li> * <li>{@link #EDGE_MODE_FAST FAST}</li> * <li>{@link #EDGE_MODE_HIGH_QUALITY HIGH_QUALITY}</li> * <li>{@link #EDGE_MODE_ZERO_SHUTTER_LAG ZERO_SHUTTER_LAG}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#EDGE_AVAILABLE_EDGE_MODES android.edge.availableEdgeModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -2329,12 +2344,13 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <p>When set to TORCH, the flash will be on continuously. This mode can be used * for use cases such as preview, auto-focus assist, still capture, or video recording.</p> * <p>The flash status will be reported by {@link CaptureResult#FLASH_STATE android.flash.state} in the capture result metadata.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #FLASH_MODE_OFF OFF}</li> * <li>{@link #FLASH_MODE_SINGLE SINGLE}</li> * <li>{@link #FLASH_MODE_TORCH TORCH}</li> - * </ul></p> + * </ul> + * * <p>This key is available on all devices.</p> * * @see CaptureRequest#CONTROL_AE_MODE @@ -2355,12 +2371,13 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <p>Hotpixel correction interpolates out, or otherwise removes, pixels * that do not accurately measure the incoming light (i.e. pixels that * are stuck at an arbitrary value or are oversensitive).</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #HOT_PIXEL_MODE_OFF OFF}</li> * <li>{@link #HOT_PIXEL_MODE_FAST FAST}</li> * <li>{@link #HOT_PIXEL_MODE_HIGH_QUALITY HIGH_QUALITY}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES android.hotPixel.availableHotPixelModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -2688,11 +2705,12 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <p>Not all devices will support OIS; see * {@link CameraCharacteristics#LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION android.lens.info.availableOpticalStabilization} for * available controls.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #LENS_OPTICAL_STABILIZATION_MODE_OFF OFF}</li> * <li>{@link #LENS_OPTICAL_STABILIZATION_MODE_ON ON}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION android.lens.info.availableOpticalStabilization}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -2738,14 +2756,15 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * will apply FAST/HIGH_QUALITY YUV domain noise reduction, respectively. The camera device * may adjust the noise reduction parameters for best image quality based on the * {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor} if it is set.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #NOISE_REDUCTION_MODE_OFF OFF}</li> * <li>{@link #NOISE_REDUCTION_MODE_FAST FAST}</li> * <li>{@link #NOISE_REDUCTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li> * <li>{@link #NOISE_REDUCTION_MODE_MINIMAL MINIMAL}</li> * <li>{@link #NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG ZERO_SHUTTER_LAG}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -2959,14 +2978,15 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <li>640x480 stream: top-left: <code>(781, 375)</code> on active array, size: <code>(640, 480)</code>, downscaled 1.17x from sensor pixels</li> * <li>1280x720 stream: top-left: <code>(711, 375)</code> on active array, size: <code>(1280, 720)</code>, upscaled 1.71x from sensor pixels</li> * </ul> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #SCALER_ROTATE_AND_CROP_NONE NONE}</li> * <li>{@link #SCALER_ROTATE_AND_CROP_90 90}</li> * <li>{@link #SCALER_ROTATE_AND_CROP_180 180}</li> * <li>{@link #SCALER_ROTATE_AND_CROP_270 270}</li> * <li>{@link #SCALER_ROTATE_AND_CROP_AUTO AUTO}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#SCALER_AVAILABLE_ROTATE_AND_CROP_MODES android.scaler.availableRotateAndCropModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -3166,7 +3186,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * occur (and that the test pattern remain unmodified, since the flash * would not actually affect it).</p> * <p>Defaults to OFF.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #SENSOR_TEST_PATTERN_MODE_OFF OFF}</li> * <li>{@link #SENSOR_TEST_PATTERN_MODE_SOLID_COLOR SOLID_COLOR}</li> @@ -3174,7 +3194,8 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <li>{@link #SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY COLOR_BARS_FADE_TO_GRAY}</li> * <li>{@link #SENSOR_TEST_PATTERN_MODE_PN9 PN9}</li> * <li>{@link #SENSOR_TEST_PATTERN_MODE_CUSTOM1 CUSTOM1}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#SENSOR_AVAILABLE_TEST_PATTERN_MODES android.sensor.availableTestPatternModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -3218,12 +3239,13 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * AWB are in AUTO modes({@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} <code>!=</code> OFF and {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode} <code>!=</code> * OFF), to get best results, it is recommended that the applications wait for the AE and AWB * to be converged before using the returned shading map data.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #SHADING_MODE_OFF OFF}</li> * <li>{@link #SHADING_MODE_FAST FAST}</li> * <li>{@link #SHADING_MODE_HIGH_QUALITY HIGH_QUALITY}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#SHADING_AVAILABLE_MODES android.shading.availableModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -3252,12 +3274,13 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <p>Whether face detection is enabled, and whether it * should output just the basic fields or the full set of * fields.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #STATISTICS_FACE_DETECT_MODE_OFF OFF}</li> * <li>{@link #STATISTICS_FACE_DETECT_MODE_SIMPLE SIMPLE}</li> * <li>{@link #STATISTICS_FACE_DETECT_MODE_FULL FULL}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES android.statistics.info.availableFaceDetectModes}</p> * <p>This key is available on all devices.</p> @@ -3295,11 +3318,12 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * android.statistics.lensShadingMap will be provided in * the output result metadata.</p> * <p>ON is always supported on devices with the RAW capability.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #STATISTICS_LENS_SHADING_MAP_MODE_OFF OFF}</li> * <li>{@link #STATISTICS_LENS_SHADING_MAP_MODE_ON ON}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES android.statistics.info.availableLensShadingMapModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -3326,11 +3350,12 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * at 30fps may have 6-7 OIS samples per capture result. This information can be combined * with the rolling shutter skew to account for lens motion during image exposure in * post-processing algorithms.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #STATISTICS_OIS_DATA_MODE_OFF OFF}</li> * <li>{@link #STATISTICS_OIS_DATA_MODE_ON ON}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_OIS_DATA_MODES android.statistics.info.availableOisDataModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -3523,14 +3548,15 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <p>If a request is sent with CONTRAST_CURVE with the camera device's * provided curve in FAST or HIGH_QUALITY, the image's tonemap will be * roughly the same.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #TONEMAP_MODE_CONTRAST_CURVE CONTRAST_CURVE}</li> * <li>{@link #TONEMAP_MODE_FAST FAST}</li> * <li>{@link #TONEMAP_MODE_HIGH_QUALITY HIGH_QUALITY}</li> * <li>{@link #TONEMAP_MODE_GAMMA_VALUE GAMMA_VALUE}</li> * <li>{@link #TONEMAP_MODE_PRESET_CURVE PRESET_CURVE}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#TONEMAP_AVAILABLE_TONE_MAP_MODES android.tonemap.availableToneMapModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -3585,11 +3611,12 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <p><img alt="Rec. 709 tonemapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png" /></p> * <p>Note that above figures show a 16 control points approximation of preset * curves. Camera devices may apply a different approximation to the curve.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #TONEMAP_PRESET_CURVE_SRGB SRGB}</li> * <li>{@link #TONEMAP_PRESET_CURVE_REC709 REC709}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * * @see CaptureRequest#TONEMAP_MODE @@ -3754,12 +3781,13 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <li>{@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}</li> * <li>{@link CaptureResult#STATISTICS_FACES android.statistics.faces}</li> * </ul> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #DISTORTION_CORRECTION_MODE_OFF OFF}</li> * <li>{@link #DISTORTION_CORRECTION_MODE_FAST FAST}</li> * <li>{@link #DISTORTION_CORRECTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES android.distortionCorrection.availableModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index 4424a71ae837..66d8b50a073e 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -449,12 +449,13 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * </code></pre> * <p>Both the input and output value ranges must match. Overflow/underflow * values are clipped to fit within the range.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #COLOR_CORRECTION_MODE_TRANSFORM_MATRIX TRANSFORM_MATRIX}</li> * <li>{@link #COLOR_CORRECTION_MODE_FAST FAST}</li> * <li>{@link #COLOR_CORRECTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * <p><b>Full capability</b> - * Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the @@ -542,12 +543,13 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * capture rate. FAST means the camera device will not slow down capture rate when * applying aberration correction.</p> * <p>LEGACY devices will always be in FAST mode.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #COLOR_CORRECTION_ABERRATION_MODE_OFF OFF}</li> * <li>{@link #COLOR_CORRECTION_ABERRATION_MODE_FAST FAST}</li> * <li>{@link #COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY HIGH_QUALITY}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES android.colorCorrection.availableAberrationModes}</p> * <p>This key is available on all devices.</p> @@ -594,13 +596,14 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * ensure it selects exposure times that do not cause banding * issues. The {@link CaptureResult#STATISTICS_SCENE_FLICKER android.statistics.sceneFlicker} key can assist * the application in this.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_AE_ANTIBANDING_MODE_OFF OFF}</li> * <li>{@link #CONTROL_AE_ANTIBANDING_MODE_50HZ 50HZ}</li> * <li>{@link #CONTROL_AE_ANTIBANDING_MODE_60HZ 60HZ}</li> * <li>{@link #CONTROL_AE_ANTIBANDING_MODE_AUTO AUTO}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br></p> * <p>{@link CameraCharacteristics#CONTROL_AE_AVAILABLE_ANTIBANDING_MODES android.control.aeAvailableAntibandingModes}</p> * <p>This key is available on all devices.</p> @@ -725,7 +728,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * camera device auto-exposure routine for the overridden * fields for a given capture will be available in its * CaptureResult.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_AE_MODE_OFF OFF}</li> * <li>{@link #CONTROL_AE_MODE_ON ON}</li> @@ -733,7 +736,8 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <li>{@link #CONTROL_AE_MODE_ON_ALWAYS_FLASH ON_ALWAYS_FLASH}</li> * <li>{@link #CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE ON_AUTO_FLASH_REDEYE}</li> * <li>{@link #CONTROL_AE_MODE_ON_EXTERNAL_FLASH ON_EXTERNAL_FLASH}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_MODES android.control.aeAvailableModes}</p> * <p>This key is available on all devices.</p> @@ -899,12 +903,13 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * example.</p> * <p>If both the precapture and the auto-focus trigger are activated on the same request, then * the camera device will complete them in the optimal order for that device.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE IDLE}</li> * <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_START START}</li> * <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL CANCEL}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * <p><b>Limited capability</b> - * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the @@ -1139,7 +1144,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * </tr> * </tbody> * </table> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_AE_STATE_INACTIVE INACTIVE}</li> * <li>{@link #CONTROL_AE_STATE_SEARCHING SEARCHING}</li> @@ -1147,7 +1152,8 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <li>{@link #CONTROL_AE_STATE_LOCKED LOCKED}</li> * <li>{@link #CONTROL_AE_STATE_FLASH_REQUIRED FLASH_REQUIRED}</li> * <li>{@link #CONTROL_AE_STATE_PRECAPTURE PRECAPTURE}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * <p><b>Limited capability</b> - * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the @@ -1184,7 +1190,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p>If the lens is controlled by the camera device auto-focus algorithm, * the camera device will report the current AF status in {@link CaptureResult#CONTROL_AF_STATE android.control.afState} * in result metadata.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_AF_MODE_OFF OFF}</li> * <li>{@link #CONTROL_AF_MODE_AUTO AUTO}</li> @@ -1192,7 +1198,8 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <li>{@link #CONTROL_AF_MODE_CONTINUOUS_VIDEO CONTINUOUS_VIDEO}</li> * <li>{@link #CONTROL_AF_MODE_CONTINUOUS_PICTURE CONTINUOUS_PICTURE}</li> * <li>{@link #CONTROL_AF_MODE_EDOF EDOF}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#CONTROL_AF_AVAILABLE_MODES android.control.afAvailableModes}</p> * <p>This key is available on all devices.</p> @@ -1307,12 +1314,13 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * focus sweep), the camera device may delay acting on a later trigger until the previous * trigger has been fully handled. This may lead to longer intervals between the trigger and * changes to {@link CaptureResult#CONTROL_AF_STATE android.control.afState}, for example.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_AF_TRIGGER_IDLE IDLE}</li> * <li>{@link #CONTROL_AF_TRIGGER_START START}</li> * <li>{@link #CONTROL_AF_TRIGGER_CANCEL CANCEL}</li> - * </ul></p> + * </ul> + * * <p>This key is available on all devices.</p> * * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER @@ -1708,7 +1716,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * </tr> * </tbody> * </table> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_AF_STATE_INACTIVE INACTIVE}</li> * <li>{@link #CONTROL_AF_STATE_PASSIVE_SCAN PASSIVE_SCAN}</li> @@ -1717,7 +1725,8 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <li>{@link #CONTROL_AF_STATE_FOCUSED_LOCKED FOCUSED_LOCKED}</li> * <li>{@link #CONTROL_AF_STATE_NOT_FOCUSED_LOCKED NOT_FOCUSED_LOCKED}</li> * <li>{@link #CONTROL_AF_STATE_PASSIVE_UNFOCUSED PASSIVE_UNFOCUSED}</li> - * </ul></p> + * </ul> + * * <p>This key is available on all devices.</p> * * @see CaptureRequest#CONTROL_AF_MODE @@ -1790,7 +1799,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}, * {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} and * {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode} are ignored.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_AWB_MODE_OFF OFF}</li> * <li>{@link #CONTROL_AWB_MODE_AUTO AUTO}</li> @@ -1801,7 +1810,8 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <li>{@link #CONTROL_AWB_MODE_CLOUDY_DAYLIGHT CLOUDY_DAYLIGHT}</li> * <li>{@link #CONTROL_AWB_MODE_TWILIGHT TWILIGHT}</li> * <li>{@link #CONTROL_AWB_MODE_SHADE SHADE}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#CONTROL_AWB_AVAILABLE_MODES android.control.awbAvailableModes}</p> * <p>This key is available on all devices.</p> @@ -1915,7 +1925,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * MANUAL_SENSOR. * * MOTION_TRACKING will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains * MOTION_TRACKING.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_CAPTURE_INTENT_CUSTOM CUSTOM}</li> * <li>{@link #CONTROL_CAPTURE_INTENT_PREVIEW PREVIEW}</li> @@ -1925,7 +1935,8 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <li>{@link #CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG ZERO_SHUTTER_LAG}</li> * <li>{@link #CONTROL_CAPTURE_INTENT_MANUAL MANUAL}</li> * <li>{@link #CONTROL_CAPTURE_INTENT_MOTION_TRACKING MOTION_TRACKING}</li> - * </ul></p> + * </ul> + * * <p>This key is available on all devices.</p> * * @see CaptureRequest#CONTROL_MODE @@ -2061,13 +2072,14 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * </tr> * </tbody> * </table> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_AWB_STATE_INACTIVE INACTIVE}</li> * <li>{@link #CONTROL_AWB_STATE_SEARCHING SEARCHING}</li> * <li>{@link #CONTROL_AWB_STATE_CONVERGED CONVERGED}</li> * <li>{@link #CONTROL_AWB_STATE_LOCKED LOCKED}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * <p><b>Limited capability</b> - * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the @@ -2096,7 +2108,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * implementor of the camera device, and should not be * depended on to be consistent (or present) across all * devices.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_EFFECT_MODE_OFF OFF}</li> * <li>{@link #CONTROL_EFFECT_MODE_MONO MONO}</li> @@ -2107,7 +2119,8 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <li>{@link #CONTROL_EFFECT_MODE_WHITEBOARD WHITEBOARD}</li> * <li>{@link #CONTROL_EFFECT_MODE_BLACKBOARD BLACKBOARD}</li> * <li>{@link #CONTROL_EFFECT_MODE_AQUA AQUA}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#CONTROL_AVAILABLE_EFFECTS android.control.availableEffects}</p> * <p>This key is available on all devices.</p> @@ -2146,14 +2159,15 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * update, as if this frame is never captured. This mode can be used in the scenario * where the application doesn't want a 3A manual control capture to affect * the subsequent auto 3A capture results.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_MODE_OFF OFF}</li> * <li>{@link #CONTROL_MODE_AUTO AUTO}</li> * <li>{@link #CONTROL_MODE_USE_SCENE_MODE USE_SCENE_MODE}</li> * <li>{@link #CONTROL_MODE_OFF_KEEP_STATE OFF_KEEP_STATE}</li> * <li>{@link #CONTROL_MODE_USE_EXTENDED_SCENE_MODE USE_EXTENDED_SCENE_MODE}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#CONTROL_AVAILABLE_MODES android.control.availableModes}</p> * <p>This key is available on all devices.</p> @@ -2183,7 +2197,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * to the implementor of the camera device. Their behavior will not be * consistent across all devices, and any given device may only implement * a subset of these modes.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_SCENE_MODE_DISABLED DISABLED}</li> * <li>{@link #CONTROL_SCENE_MODE_FACE_PRIORITY FACE_PRIORITY}</li> @@ -2204,7 +2218,8 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <li>{@link #CONTROL_SCENE_MODE_BARCODE BARCODE}</li> * <li>{@link #CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO}</li> * <li>{@link #CONTROL_SCENE_MODE_HDR HDR}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}</p> * <p>This key is available on all devices.</p> @@ -2265,11 +2280,12 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * ({@link CaptureRequest#LENS_OPTICAL_STABILIZATION_MODE android.lens.opticalStabilizationMode}), turning both modes on may * produce undesirable interaction, so it is recommended not to enable * both at the same time.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_VIDEO_STABILIZATION_MODE_OFF OFF}</li> * <li>{@link #CONTROL_VIDEO_STABILIZATION_MODE_ON ON}</li> - * </ul></p> + * </ul> + * * <p>This key is available on all devices.</p> * * @see CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE @@ -2362,11 +2378,12 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * result. Otherwise the value will be NOT_DETECTED. The threshold for detection is similar * to what would trigger a new passive focus scan to begin in CONTINUOUS autofocus modes.</p> * <p>This key will be available if the camera device advertises this key via {@link android.hardware.camera2.CameraCharacteristics#getAvailableCaptureResultKeys }.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_AF_SCENE_CHANGE_NOT_DETECTED NOT_DETECTED}</li> * <li>{@link #CONTROL_AF_SCENE_CHANGE_DETECTED DETECTED}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * @see #CONTROL_AF_SCENE_CHANGE_NOT_DETECTED * @see #CONTROL_AF_SCENE_CHANGE_DETECTED @@ -2402,12 +2419,13 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * with different field of view. As a result, when bokeh mode is enabled, the camera device * may override {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} or {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}, and the field of * view may be smaller than when bokeh mode is off.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #CONTROL_EXTENDED_SCENE_MODE_DISABLED DISABLED}</li> * <li>{@link #CONTROL_EXTENDED_SCENE_MODE_BOKEH_STILL_CAPTURE BOKEH_STILL_CAPTURE}</li> * <li>{@link #CONTROL_EXTENDED_SCENE_MODE_BOKEH_CONTINUOUS BOKEH_CONTINUOUS}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * * @see CaptureRequest#CONTROL_ZOOM_RATIO @@ -2534,13 +2552,14 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * device will apply FAST/HIGH_QUALITY YUV-domain edge enhancement, respectively. * The camera device may adjust its internal edge enhancement parameters for best * image quality based on the {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor}, if it is set.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #EDGE_MODE_OFF OFF}</li> * <li>{@link #EDGE_MODE_FAST FAST}</li> * <li>{@link #EDGE_MODE_HIGH_QUALITY HIGH_QUALITY}</li> * <li>{@link #EDGE_MODE_ZERO_SHUTTER_LAG ZERO_SHUTTER_LAG}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#EDGE_AVAILABLE_EDGE_MODES android.edge.availableEdgeModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -2576,12 +2595,13 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p>When set to TORCH, the flash will be on continuously. This mode can be used * for use cases such as preview, auto-focus assist, still capture, or video recording.</p> * <p>The flash status will be reported by {@link CaptureResult#FLASH_STATE android.flash.state} in the capture result metadata.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #FLASH_MODE_OFF OFF}</li> * <li>{@link #FLASH_MODE_SINGLE SINGLE}</li> * <li>{@link #FLASH_MODE_TORCH TORCH}</li> - * </ul></p> + * </ul> + * * <p>This key is available on all devices.</p> * * @see CaptureRequest#CONTROL_AE_MODE @@ -2613,14 +2633,15 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * </ul> * <p>In all other conditions the state will not be available on * LEGACY devices (i.e. it will be <code>null</code>).</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #FLASH_STATE_UNAVAILABLE UNAVAILABLE}</li> * <li>{@link #FLASH_STATE_CHARGING CHARGING}</li> * <li>{@link #FLASH_STATE_READY READY}</li> * <li>{@link #FLASH_STATE_FIRED FIRED}</li> * <li>{@link #FLASH_STATE_PARTIAL PARTIAL}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * <p><b>Limited capability</b> - * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the @@ -2646,12 +2667,13 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p>Hotpixel correction interpolates out, or otherwise removes, pixels * that do not accurately measure the incoming light (i.e. pixels that * are stuck at an arbitrary value or are oversensitive).</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #HOT_PIXEL_MODE_OFF OFF}</li> * <li>{@link #HOT_PIXEL_MODE_FAST FAST}</li> * <li>{@link #HOT_PIXEL_MODE_HIGH_QUALITY HIGH_QUALITY}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES android.hotPixel.availableHotPixelModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -2988,11 +3010,12 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p>Not all devices will support OIS; see * {@link CameraCharacteristics#LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION android.lens.info.availableOpticalStabilization} for * available controls.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #LENS_OPTICAL_STABILIZATION_MODE_OFF OFF}</li> * <li>{@link #LENS_OPTICAL_STABILIZATION_MODE_ON ON}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION android.lens.info.availableOpticalStabilization}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -3032,11 +3055,12 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p>Then this state will always be STATIONARY.</p> * <p>When the state is MOVING, it indicates that at least one of the lens parameters * is changing.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #LENS_STATE_STATIONARY STATIONARY}</li> * <li>{@link #LENS_STATE_MOVING MOVING}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * <p><b>Limited capability</b> - * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the @@ -3338,14 +3362,15 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * will apply FAST/HIGH_QUALITY YUV domain noise reduction, respectively. The camera device * may adjust the noise reduction parameters for best image quality based on the * {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor} if it is set.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #NOISE_REDUCTION_MODE_OFF OFF}</li> * <li>{@link #NOISE_REDUCTION_MODE_FAST FAST}</li> * <li>{@link #NOISE_REDUCTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li> * <li>{@link #NOISE_REDUCTION_MODE_MINIMAL MINIMAL}</li> * <li>{@link #NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG ZERO_SHUTTER_LAG}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -3622,14 +3647,15 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <li>640x480 stream: top-left: <code>(781, 375)</code> on active array, size: <code>(640, 480)</code>, downscaled 1.17x from sensor pixels</li> * <li>1280x720 stream: top-left: <code>(711, 375)</code> on active array, size: <code>(1280, 720)</code>, upscaled 1.71x from sensor pixels</li> * </ul> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #SCALER_ROTATE_AND_CROP_NONE NONE}</li> * <li>{@link #SCALER_ROTATE_AND_CROP_90 90}</li> * <li>{@link #SCALER_ROTATE_AND_CROP_180 180}</li> * <li>{@link #SCALER_ROTATE_AND_CROP_270 270}</li> * <li>{@link #SCALER_ROTATE_AND_CROP_AUTO AUTO}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#SCALER_AVAILABLE_ROTATE_AND_CROP_MODES android.scaler.availableRotateAndCropModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -3951,7 +3977,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * occur (and that the test pattern remain unmodified, since the flash * would not actually affect it).</p> * <p>Defaults to OFF.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #SENSOR_TEST_PATTERN_MODE_OFF OFF}</li> * <li>{@link #SENSOR_TEST_PATTERN_MODE_SOLID_COLOR SOLID_COLOR}</li> @@ -3959,7 +3985,8 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <li>{@link #SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY COLOR_BARS_FADE_TO_GRAY}</li> * <li>{@link #SENSOR_TEST_PATTERN_MODE_PN9 PN9}</li> * <li>{@link #SENSOR_TEST_PATTERN_MODE_CUSTOM1 CUSTOM1}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#SENSOR_AVAILABLE_TEST_PATTERN_MODES android.sensor.availableTestPatternModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -4105,12 +4132,13 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * AWB are in AUTO modes({@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} <code>!=</code> OFF and {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode} <code>!=</code> * OFF), to get best results, it is recommended that the applications wait for the AE and AWB * to be converged before using the returned shading map data.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #SHADING_MODE_OFF OFF}</li> * <li>{@link #SHADING_MODE_FAST FAST}</li> * <li>{@link #SHADING_MODE_HIGH_QUALITY HIGH_QUALITY}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#SHADING_AVAILABLE_MODES android.shading.availableModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -4139,12 +4167,13 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p>Whether face detection is enabled, and whether it * should output just the basic fields or the full set of * fields.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #STATISTICS_FACE_DETECT_MODE_OFF OFF}</li> * <li>{@link #STATISTICS_FACE_DETECT_MODE_SIMPLE SIMPLE}</li> * <li>{@link #STATISTICS_FACE_DETECT_MODE_FULL FULL}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES android.statistics.info.availableFaceDetectModes}</p> * <p>This key is available on all devices.</p> @@ -4509,12 +4538,13 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * into this metadata field. See * {@link CaptureRequest#CONTROL_AE_ANTIBANDING_MODE android.control.aeAntibandingMode} for more details.</p> * <p>Reports NONE if there doesn't appear to be flickering illumination.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #STATISTICS_SCENE_FLICKER_NONE NONE}</li> * <li>{@link #STATISTICS_SCENE_FLICKER_50HZ 50HZ}</li> * <li>{@link #STATISTICS_SCENE_FLICKER_60HZ 60HZ}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * <p><b>Full capability</b> - * Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the @@ -4578,11 +4608,12 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * android.statistics.lensShadingMap will be provided in * the output result metadata.</p> * <p>ON is always supported on devices with the RAW capability.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #STATISTICS_LENS_SHADING_MAP_MODE_OFF OFF}</li> * <li>{@link #STATISTICS_LENS_SHADING_MAP_MODE_ON ON}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES android.statistics.info.availableLensShadingMapModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -4609,11 +4640,12 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * at 30fps may have 6-7 OIS samples per capture result. This information can be combined * with the rolling shutter skew to account for lens motion during image exposure in * post-processing algorithms.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #STATISTICS_OIS_DATA_MODE_OFF OFF}</li> * <li>{@link #STATISTICS_OIS_DATA_MODE_ON ON}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_OIS_DATA_MODES android.statistics.info.availableOisDataModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -4881,14 +4913,15 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p>If a request is sent with CONTRAST_CURVE with the camera device's * provided curve in FAST or HIGH_QUALITY, the image's tonemap will be * roughly the same.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #TONEMAP_MODE_CONTRAST_CURVE CONTRAST_CURVE}</li> * <li>{@link #TONEMAP_MODE_FAST FAST}</li> * <li>{@link #TONEMAP_MODE_HIGH_QUALITY HIGH_QUALITY}</li> * <li>{@link #TONEMAP_MODE_GAMMA_VALUE GAMMA_VALUE}</li> * <li>{@link #TONEMAP_MODE_PRESET_CURVE PRESET_CURVE}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#TONEMAP_AVAILABLE_TONE_MAP_MODES android.tonemap.availableToneMapModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> @@ -4943,11 +4976,12 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p><img alt="Rec. 709 tonemapping curve" src="/reference/images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png" /></p> * <p>Note that above figures show a 16 control points approximation of preset * curves. Camera devices may apply a different approximation to the curve.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #TONEMAP_PRESET_CURVE_SRGB SRGB}</li> * <li>{@link #TONEMAP_PRESET_CURVE_REC709 REC709}</li> - * </ul></p> + * </ul> + * * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> * * @see CaptureRequest#TONEMAP_MODE @@ -5048,11 +5082,12 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p>In other words, results for this current request and up to * {@link CameraCharacteristics#REQUEST_PIPELINE_MAX_DEPTH android.request.pipelineMaxDepth} prior requests may have their * android.sync.frameNumber change to CONVERGING.</p> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #SYNC_FRAME_NUMBER_CONVERGING CONVERGING}</li> * <li>{@link #SYNC_FRAME_NUMBER_UNKNOWN UNKNOWN}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * Either a non-negative value corresponding to a * <code>frame_number</code>, or one of the two enums (CONVERGING / UNKNOWN).</p> @@ -5174,12 +5209,13 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <li>{@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}</li> * <li>{@link CaptureResult#STATISTICS_FACES android.statistics.faces}</li> * </ul> - * <p><b>Possible values:</b> + * <p><b>Possible values:</b></p> * <ul> * <li>{@link #DISTORTION_CORRECTION_MODE_OFF OFF}</li> * <li>{@link #DISTORTION_CORRECTION_MODE_FAST FAST}</li> * <li>{@link #DISTORTION_CORRECTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li> - * </ul></p> + * </ul> + * * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES android.distortionCorrection.availableModes}</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> diff --git a/core/java/android/hardware/display/OWNERS b/core/java/android/hardware/display/OWNERS index 9ca391013aa3..5bcd9bb87c7a 100644 --- a/core/java/android/hardware/display/OWNERS +++ b/core/java/android/hardware/display/OWNERS @@ -1,2 +1,6 @@ +# Bug component: 345010 + +include /services/core/java/com/android/server/display/OWNERS + michaelwr@google.com santoscordon@google.com diff --git a/core/java/android/hardware/face/OWNERS b/core/java/android/hardware/face/OWNERS new file mode 100644 index 000000000000..33527f824827 --- /dev/null +++ b/core/java/android/hardware/face/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 879035 + +jaggies@google.com diff --git a/core/java/android/hardware/fingerprint/OWNERS b/core/java/android/hardware/fingerprint/OWNERS new file mode 100644 index 000000000000..dcead40d482d --- /dev/null +++ b/core/java/android/hardware/fingerprint/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 114777 + +jaggies@google.com diff --git a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java index c6007f1184f5..a8cafef844f1 100644 --- a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java +++ b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java @@ -19,6 +19,7 @@ package android.hardware.hdmi; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.hardware.hdmi.HdmiControlManager.HdmiCecVersion; import android.os.Parcel; import android.os.Parcelable; @@ -107,6 +108,8 @@ public class HdmiDeviceInfo implements Parcelable { // CEC only parameters. private final int mLogicalAddress; private final int mDeviceType; + @HdmiCecVersion + private final int mHdmiCecVersion; private final int mVendorId; private final String mDisplayName; private final int mDevicePowerStatus; @@ -133,8 +136,9 @@ public class HdmiDeviceInfo implements Parcelable { int vendorId = source.readInt(); int powerStatus = source.readInt(); String displayName = source.readString(); + int cecVersion = source.readInt(); return new HdmiDeviceInfo(logicalAddress, physicalAddress, portId, - deviceType, vendorId, displayName, powerStatus); + deviceType, vendorId, displayName, powerStatus, cecVersion); case HDMI_DEVICE_TYPE_MHL: int deviceId = source.readInt(); int adopterId = source.readInt(); @@ -167,7 +171,7 @@ public class HdmiDeviceInfo implements Parcelable { * @hide */ public HdmiDeviceInfo(int logicalAddress, int physicalAddress, int portId, int deviceType, - int vendorId, String displayName, int powerStatus) { + int vendorId, String displayName, int powerStatus, int hdmiCecVersion) { mHdmiDeviceType = HDMI_DEVICE_TYPE_CEC; mPhysicalAddress = physicalAddress; mPortId = portId; @@ -175,6 +179,7 @@ public class HdmiDeviceInfo implements Parcelable { mId = idForCecDevice(logicalAddress); mLogicalAddress = logicalAddress; mDeviceType = deviceType; + mHdmiCecVersion = hdmiCecVersion; mVendorId = vendorId; mDevicePowerStatus = powerStatus; mDisplayName = displayName; @@ -192,12 +197,31 @@ public class HdmiDeviceInfo implements Parcelable { * @param deviceType type of device * @param vendorId vendor id of device. Used for vendor specific command. * @param displayName name of device + * @param powerStatus device power status + * @hide + */ + public HdmiDeviceInfo(int logicalAddress, int physicalAddress, int portId, int deviceType, + int vendorId, String displayName, int powerStatus) { + this(logicalAddress, physicalAddress, portId, deviceType, + vendorId, displayName, powerStatus, HdmiControlManager.HDMI_CEC_VERSION_1_4_b); + } + + /** + * Constructor. Used to initialize the instance for CEC device. + * + * @param logicalAddress logical address of HDMI-CEC device + * @param physicalAddress physical address of HDMI-CEC device + * @param portId HDMI port ID (1 for HDMI1) + * @param deviceType type of device + * @param vendorId vendor id of device. Used for vendor specific command. + * @param displayName name of device * @hide */ public HdmiDeviceInfo(int logicalAddress, int physicalAddress, int portId, int deviceType, int vendorId, String displayName) { this(logicalAddress, physicalAddress, portId, deviceType, - vendorId, displayName, HdmiControlManager.POWER_STATUS_UNKNOWN); + vendorId, displayName, HdmiControlManager.POWER_STATUS_UNKNOWN, + HdmiControlManager.HDMI_CEC_VERSION_1_4_b); } /** @@ -215,6 +239,7 @@ public class HdmiDeviceInfo implements Parcelable { mId = idForHardware(portId); mLogicalAddress = -1; mDeviceType = DEVICE_RESERVED; + mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b; mVendorId = 0; mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN; mDisplayName = "HDMI" + portId; @@ -240,6 +265,7 @@ public class HdmiDeviceInfo implements Parcelable { mId = idForMhlDevice(portId); mLogicalAddress = -1; mDeviceType = DEVICE_RESERVED; + mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b; mVendorId = 0; mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN; mDisplayName = "Mobile"; @@ -261,6 +287,7 @@ public class HdmiDeviceInfo implements Parcelable { mLogicalAddress = -1; mDeviceType = DEVICE_INACTIVE; + mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b; mPortId = PORT_INVALID; mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN; mDisplayName = "Inactive"; @@ -339,6 +366,16 @@ public class HdmiDeviceInfo implements Parcelable { } /** + * Returns the CEC version the device supports. + * + * @hide + */ + @HdmiCecVersion + public int getCecVersion() { + return mHdmiCecVersion; + } + + /** * Returns device's power status. It should be one of the following values. * <ul> * <li>{@link HdmiControlManager#POWER_STATUS_ON} @@ -448,6 +485,7 @@ public class HdmiDeviceInfo implements Parcelable { dest.writeInt(mVendorId); dest.writeInt(mDevicePowerStatus); dest.writeString(mDisplayName); + dest.writeInt(mHdmiCecVersion); break; case HDMI_DEVICE_TYPE_MHL: dest.writeInt(mDeviceId); @@ -470,6 +508,7 @@ public class HdmiDeviceInfo implements Parcelable { s.append("logical_address: ").append(String.format("0x%02X", mLogicalAddress)); s.append(" "); s.append("device_type: ").append(mDeviceType).append(" "); + s.append("cec_version: ").append(mHdmiCecVersion).append(" "); s.append("vendor_id: ").append(mVendorId).append(" "); s.append("display_name: ").append(mDisplayName).append(" "); s.append("power_status: ").append(mDevicePowerStatus).append(" "); @@ -507,6 +546,7 @@ public class HdmiDeviceInfo implements Parcelable { && mPortId == other.mPortId && mLogicalAddress == other.mLogicalAddress && mDeviceType == other.mDeviceType + && mHdmiCecVersion == other.mHdmiCecVersion && mVendorId == other.mVendorId && mDevicePowerStatus == other.mDevicePowerStatus && mDisplayName.equals(other.mDisplayName) @@ -522,6 +562,7 @@ public class HdmiDeviceInfo implements Parcelable { mPortId, mLogicalAddress, mDeviceType, + mHdmiCecVersion, mVendorId, mDevicePowerStatus, mDisplayName, diff --git a/core/java/android/hardware/hdmi/OWNERS b/core/java/android/hardware/hdmi/OWNERS new file mode 100644 index 000000000000..16c15e387bab --- /dev/null +++ b/core/java/android/hardware/hdmi/OWNERS @@ -0,0 +1,6 @@ +# Bug component: 826094 + +include /services/core/java/com/android/server/display/OWNERS + +marvinramin@google.com +nchalko@google.com diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl index dc6f5799156d..57c039831112 100644 --- a/core/java/android/hardware/input/IInputManager.aidl +++ b/core/java/android/hardware/input/IInputManager.aidl @@ -22,6 +22,7 @@ import android.hardware.input.KeyboardLayout; import android.hardware.input.IInputDevicesChangedListener; import android.hardware.input.ITabletModeChangedListener; import android.hardware.input.TouchCalibration; +import android.os.CombinedVibrationEffect; import android.os.IBinder; import android.os.VibrationEffect; import android.view.InputDevice; @@ -85,7 +86,10 @@ interface IInputManager { // Input device vibrator control. void vibrate(int deviceId, in VibrationEffect effect, IBinder token); + void vibrateCombined(int deviceId, in CombinedVibrationEffect effect, IBinder token); void cancelVibrate(int deviceId, IBinder token); + int[] getVibratorIds(int deviceId); + boolean isVibrating(int deviceId); void setPointerIconType(int typeId); void setCustomPointerIcon(in PointerIcon icon); diff --git a/core/java/android/hardware/input/InputDeviceVibrator.java b/core/java/android/hardware/input/InputDeviceVibrator.java new file mode 100644 index 000000000000..c60d6ce46fdb --- /dev/null +++ b/core/java/android/hardware/input/InputDeviceVibrator.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.input; + +import android.annotation.CallbackExecutor; +import android.annotation.NonNull; +import android.os.Binder; +import android.os.VibrationAttributes; +import android.os.VibrationEffect; +import android.os.Vibrator; + +import java.util.concurrent.Executor; + +/** + * Vibrator implementation that communicates with the input device vibrators. + */ +final class InputDeviceVibrator extends Vibrator { + // mDeviceId represents InputDevice ID the vibrator belongs to + private final int mDeviceId; + private final int mVibratorId; + private final Binder mToken; + private final InputManager mInputManager; + + InputDeviceVibrator(InputManager inputManager, int deviceId, int vibratorId) { + mInputManager = inputManager; + mDeviceId = deviceId; + mVibratorId = vibratorId; + mToken = new Binder(); + } + + @Override + public boolean hasVibrator() { + return true; + } + + @Override + public boolean isVibrating() { + return mInputManager.isVibrating(mDeviceId); + } + + /* TODO: b/161634264 Support Vibrator listener API in input devices */ + @Override + public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) { + throw new UnsupportedOperationException( + "addVibratorStateListener not supported in InputDeviceVibrator"); + } + + @Override + public void addVibratorStateListener( + @NonNull @CallbackExecutor Executor executor, + @NonNull OnVibratorStateChangedListener listener) { + throw new UnsupportedOperationException( + "addVibratorStateListener not supported in InputDeviceVibrator"); + } + + @Override + public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) { + throw new UnsupportedOperationException( + "removeVibratorStateListener not supported in InputDeviceVibrator"); + } + + @Override + public boolean hasAmplitudeControl() { + return true; + } + + /** + * @hide + */ + @Override + public void vibrate(int uid, String opPkg, @NonNull VibrationEffect effect, + String reason, @NonNull VibrationAttributes attributes) { + mInputManager.vibrate(mDeviceId, effect, mToken); + } + + @Override + public void cancel() { + mInputManager.cancelVibrate(mDeviceId, mToken); + } +} diff --git a/core/java/android/hardware/input/InputDeviceVibratorManager.java b/core/java/android/hardware/input/InputDeviceVibratorManager.java new file mode 100644 index 000000000000..a381b02ab2a6 --- /dev/null +++ b/core/java/android/hardware/input/InputDeviceVibratorManager.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.input; + +import android.os.Binder; +import android.os.CombinedVibrationEffect; +import android.os.NullVibrator; +import android.os.Vibrator; +import android.os.VibratorManager; +import android.util.SparseArray; +import android.view.InputDevice; + +import com.android.internal.annotations.GuardedBy; + +/** + * Vibrator manager implementation that communicates with the input device vibrators. + * + * @hide + */ +public class InputDeviceVibratorManager extends VibratorManager + implements InputManager.InputDeviceListener { + private static final String TAG = "InputDeviceVibratorManager"; + private static final boolean DEBUG = false; + + private final Binder mToken; + private final InputManager mInputManager; + + // The input device Id. + private final int mDeviceId; + // Vibrator map from Vibrator Id to Vibrator + @GuardedBy("mVibrators") + private final SparseArray<Vibrator> mVibrators = new SparseArray<>(); + + public InputDeviceVibratorManager(InputManager inputManager, int deviceId) { + mInputManager = inputManager; + mDeviceId = deviceId; + mToken = new Binder(); + + initializeVibrators(); + } + + private void initializeVibrators() { + synchronized (mVibrators) { + mVibrators.clear(); + InputDevice inputDevice = InputDevice.getDevice(mDeviceId); + final int[] vibratorIds = + mInputManager.getVibratorIds(mDeviceId); + for (int i = 0; i < vibratorIds.length; i++) { + mVibrators.put(vibratorIds[i], + new InputDeviceVibrator(mInputManager, mDeviceId, vibratorIds[i])); + } + } + } + + @Override + public void onInputDeviceAdded(int deviceId) { + } + + @Override + public void onInputDeviceRemoved(int deviceId) { + synchronized (mVibrators) { + if (deviceId == mDeviceId) { + mVibrators.clear(); + } + } + } + + @Override + public void onInputDeviceChanged(int deviceId) { + if (deviceId == mDeviceId) { + initializeVibrators(); + } + } + + @Override + public int[] getVibratorIds() { + synchronized (mVibrators) { + int[] vibratorIds = new int[mVibrators.size()]; + for (int idx = 0; idx < mVibrators.size(); idx++) { + vibratorIds[idx++] = mVibrators.keyAt(idx); + } + return vibratorIds; + } + } + + @Override + public Vibrator getVibrator(int vibratorId) { + synchronized (mVibrators) { + if (mVibrators.contains(vibratorId)) { + return mVibrators.get(vibratorId); + } + } + return NullVibrator.getInstance(); + } + + @Override + public Vibrator getDefaultVibrator() { + // Returns vibrator ID 0 + synchronized (mVibrators) { + if (mVibrators.size() > 0) { + return mVibrators.valueAt(0); + } + } + return NullVibrator.getInstance(); + } + + @Override + public void vibrate(CombinedVibrationEffect effect) { + mInputManager.vibrate(mDeviceId, effect, mToken); + } +} diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index 81ea2f5a17dd..40c7e9a892ff 100644 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -17,7 +17,6 @@ package android.hardware.input; import android.Manifest; -import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -29,9 +28,9 @@ import android.annotation.TestApi; import android.compat.annotation.ChangeId; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; -import android.os.Binder; import android.os.BlockUntrustedTouchesMode; import android.os.Build; +import android.os.CombinedVibrationEffect; import android.os.Handler; import android.os.IBinder; import android.os.InputEventInjectionSync; @@ -41,9 +40,9 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.os.SystemClock; -import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.Vibrator; +import android.os.VibratorManager; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Log; @@ -64,7 +63,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.Executor; /** * Provides information about input devices and available key layouts. @@ -210,6 +208,14 @@ public final class InputManager { public static final long BLOCK_UNTRUSTED_TOUCHES = 158002302L; /** + * Check whether apps are using FLAG_SLIPPERY for their windows. We expect that this flag is + * only used by the system components. If so, we can lock it down. + * @hide + */ + @ChangeId + public static final long BLOCK_FLAG_SLIPPERY = android.os.IInputConstants.BLOCK_FLAG_SLIPPERY; + + /** * Input Event Injection Synchronization Mode: None. * Never blocks. Injection is asynchronous and is assumed always to be successful. * @hide @@ -1287,8 +1293,75 @@ public final class InputManager { * @return The vibrator, never null. * @hide */ - public Vibrator getInputDeviceVibrator(int deviceId) { - return new InputDeviceVibrator(deviceId); + public Vibrator getInputDeviceVibrator(int deviceId, int vibratorId) { + return new InputDeviceVibrator(this, deviceId, vibratorId); + } + + /** + * Gets a vibrator manager service associated with an input device, always create a new + * instance. + * @return The vibrator manager, never null. + * @hide + */ + @NonNull + public VibratorManager getInputDeviceVibratorManager(int deviceId) { + return new InputDeviceVibratorManager(InputManager.this, deviceId); + } + + /* + * Get the list of device vibrators + * @return The list of vibrators IDs + */ + int[] getVibratorIds(int deviceId) { + try { + return mIm.getVibratorIds(deviceId); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + } + + /* + * Perform vibration effect + */ + void vibrate(int deviceId, VibrationEffect effect, IBinder token) { + try { + mIm.vibrate(deviceId, effect, token); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + } + + /* + * Perform combined vibration effect + */ + void vibrate(int deviceId, CombinedVibrationEffect effect, IBinder token) { + try { + mIm.vibrateCombined(deviceId, effect, token); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + } + + /* + * Cancel an ongoing vibration + */ + void cancelVibrate(int deviceId, IBinder token) { + try { + mIm.cancelVibrate(deviceId, token); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + } + + /* + * Check if input device is vibrating + */ + boolean isVibrating(int deviceId) { + try { + return mIm.isVibrating(deviceId); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } } /** @@ -1401,72 +1474,4 @@ public final class InputManager { } } } - - private final class InputDeviceVibrator extends Vibrator { - private final int mDeviceId; - private final Binder mToken; - - public InputDeviceVibrator(int deviceId) { - mDeviceId = deviceId; - mToken = new Binder(); - } - - @Override - public boolean hasVibrator() { - return true; - } - - @Override - public boolean isVibrating() { - throw new UnsupportedOperationException( - "isVibrating not supported in InputDeviceVibrator"); - } - - @Override - public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) { - throw new UnsupportedOperationException( - "addVibratorStateListener not supported in InputDeviceVibrator"); - } - - @Override - public void addVibratorStateListener( - @NonNull @CallbackExecutor Executor executor, - @NonNull OnVibratorStateChangedListener listener) { - throw new UnsupportedOperationException( - "addVibratorStateListener not supported in InputDeviceVibrator"); - } - - @Override - public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) { - throw new UnsupportedOperationException( - "removeVibratorStateListener not supported in InputDeviceVibrator"); - } - - @Override - public boolean hasAmplitudeControl() { - return true; - } - - /** - * @hide - */ - @Override - public void vibrate(int uid, String opPkg, @NonNull VibrationEffect effect, - String reason, @NonNull VibrationAttributes attributes) { - try { - mIm.vibrate(mDeviceId, effect, mToken); - } catch (RemoteException ex) { - throw ex.rethrowFromSystemServer(); - } - } - - @Override - public void cancel() { - try { - mIm.cancelVibrate(mDeviceId, mToken); - } catch (RemoteException ex) { - throw ex.rethrowFromSystemServer(); - } - } - } } diff --git a/core/java/android/hardware/input/OWNERS b/core/java/android/hardware/input/OWNERS index 0313a40f7270..25e02e1aa6f3 100644 --- a/core/java/android/hardware/input/OWNERS +++ b/core/java/android/hardware/input/OWNERS @@ -1,2 +1,6 @@ +# Bug component: 136048 + +include /services/core/java/com/android/server/input/OWNERS + michaelwr@google.com svv@google.com diff --git a/core/java/android/hardware/iris/OWNERS b/core/java/android/hardware/iris/OWNERS new file mode 100644 index 000000000000..33527f824827 --- /dev/null +++ b/core/java/android/hardware/iris/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 879035 + +jaggies@google.com diff --git a/core/java/android/hardware/lights/OWNERS b/core/java/android/hardware/lights/OWNERS new file mode 100644 index 000000000000..cb46a80d9b60 --- /dev/null +++ b/core/java/android/hardware/lights/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/lights/OWNERS diff --git a/core/java/android/hardware/location/OWNERS b/core/java/android/hardware/location/OWNERS new file mode 100644 index 000000000000..383321bc3d69 --- /dev/null +++ b/core/java/android/hardware/location/OWNERS @@ -0,0 +1,6 @@ +# Bug component: 880425 + +mstogaitis@google.com +wyattriley@google.com +etn@google.com +weiwa@google.com diff --git a/core/java/android/hardware/soundtrigger/OWNERS b/core/java/android/hardware/soundtrigger/OWNERS new file mode 100644 index 000000000000..816bc6bba639 --- /dev/null +++ b/core/java/android/hardware/soundtrigger/OWNERS @@ -0,0 +1 @@ +include /core/java/android/media/soundtrigger/OWNERS diff --git a/core/java/android/hardware/usb/OWNERS b/core/java/android/hardware/usb/OWNERS index 8ee72b577f3c..8f2b39da4f63 100644 --- a/core/java/android/hardware/usb/OWNERS +++ b/core/java/android/hardware/usb/OWNERS @@ -1,6 +1,4 @@ -badhri@google.com -elaurent@google.com +# Bug component: 175220 + moltmann@google.com -albertccwang@google.com -jameswei@google.com -howardyen@google.com
\ No newline at end of file +badhri@google.com diff --git a/core/java/android/inputmethodservice/OWNERS b/core/java/android/inputmethodservice/OWNERS index 444719701df2..e6a04dad25c2 100644 --- a/core/java/android/inputmethodservice/OWNERS +++ b/core/java/android/inputmethodservice/OWNERS @@ -1,3 +1,4 @@ +# Bug component: 34867 set noparent -include ../../../../services/core/java/com/android/server/inputmethod/OWNERS +include /services/core/java/com/android/server/inputmethod/OWNERS diff --git a/core/java/android/metrics/OWNERS b/core/java/android/metrics/OWNERS new file mode 100644 index 000000000000..ba867e0cad2b --- /dev/null +++ b/core/java/android/metrics/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 26805 + +cwren@android.com +cwren@google.com diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 8dad11ffa731..1a37fb9fb690 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -975,6 +975,10 @@ public final class NetworkCapabilities implements Parcelable { return mOwnerUid; } + private boolean equalsOwnerUid(@NonNull final NetworkCapabilities nc) { + return mOwnerUid == nc.mOwnerUid; + } + /** * UIDs of packages that are administrators of this network, or empty if none. * @@ -1684,6 +1688,7 @@ public final class NetworkCapabilities implements Parcelable { && equalsTransportInfo(that) && equalsUids(that) && equalsSSID(that) + && equalsOwnerUid(that) && equalsPrivateDnsBroken(that) && equalsRequestor(that) && equalsAdministratorUids(that); @@ -1697,17 +1702,18 @@ public final class NetworkCapabilities implements Parcelable { + ((int) (mUnwantedNetworkCapabilities >> 32) * 7) + ((int) (mTransportTypes & 0xFFFFFFFF) * 11) + ((int) (mTransportTypes >> 32) * 13) - + (mLinkUpBandwidthKbps * 17) - + (mLinkDownBandwidthKbps * 19) + + mLinkUpBandwidthKbps * 17 + + mLinkDownBandwidthKbps * 19 + Objects.hashCode(mNetworkSpecifier) * 23 - + (mSignalStrength * 29) - + Objects.hashCode(mUids) * 31 - + Objects.hashCode(mSSID) * 37 - + Objects.hashCode(mTransportInfo) * 41 - + Objects.hashCode(mPrivateDnsBroken) * 43 - + Objects.hashCode(mRequestorUid) * 47 - + Objects.hashCode(mRequestorPackageName) * 53 - + Arrays.hashCode(mAdministratorUids) * 59; + + mSignalStrength * 29 + + mOwnerUid * 31 + + Objects.hashCode(mUids) * 37 + + Objects.hashCode(mSSID) * 41 + + Objects.hashCode(mTransportInfo) * 43 + + Objects.hashCode(mPrivateDnsBroken) * 47 + + Objects.hashCode(mRequestorUid) * 53 + + Objects.hashCode(mRequestorPackageName) * 59 + + Arrays.hashCode(mAdministratorUids) * 61; } @Override diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index a0faafa779a8..d84ee2a87b43 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -35,7 +35,6 @@ import java.net.Inet4Address; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; -import java.util.Collection; import java.util.Locale; import java.util.TreeSet; @@ -342,20 +341,6 @@ public class NetworkUtils { } /** - * Create a string array of host addresses from a collection of InetAddresses - * @param addrs a Collection of InetAddresses - * @return an array of Strings containing their host addresses - */ - public static String[] makeStrings(Collection<InetAddress> addrs) { - String[] result = new String[addrs.size()]; - int i = 0; - for (InetAddress addr : addrs) { - result[i++] = addr.getHostAddress(); - } - return result; - } - - /** * Trim leading zeros from IPv4 address strings * Our base libraries will interpret that as octel.. * Must leave non v4 addresses and host names alone. diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS index 5e2a71876103..2f8f685af40b 100644 --- a/core/java/android/net/OWNERS +++ b/core/java/android/net/OWNERS @@ -2,7 +2,7 @@ set noparent codewiz@google.com jchalard@google.com -jsharkey@android.com +jsharkey@google.com junyulai@google.com lorenzo@google.com reminv@google.com diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java index f1d9669a8309..20ccc07b18dd 100644 --- a/core/java/android/net/Proxy.java +++ b/core/java/android/net/Proxy.java @@ -205,7 +205,7 @@ public final class Proxy { if (host.equalsIgnoreCase("localhost")) { return true; } - if (NetworkUtils.numericToInetAddress(host).isLoopbackAddress()) { + if (InetAddresses.parseNumericAddress(host).isLoopbackAddress()) { return true; } } diff --git a/core/java/android/nfc/OWNERS b/core/java/android/nfc/OWNERS new file mode 100644 index 000000000000..6aaf039244c9 --- /dev/null +++ b/core/java/android/nfc/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 48448 + +zachoverflow@google.com +alisher@google.com diff --git a/core/java/android/nfc/cardemulation/OWNERS b/core/java/android/nfc/cardemulation/OWNERS new file mode 100644 index 000000000000..6aaf039244c9 --- /dev/null +++ b/core/java/android/nfc/cardemulation/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 48448 + +zachoverflow@google.com +alisher@google.com diff --git a/core/java/android/nfc/dta/OWNERS b/core/java/android/nfc/dta/OWNERS new file mode 100644 index 000000000000..6aaf039244c9 --- /dev/null +++ b/core/java/android/nfc/dta/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 48448 + +zachoverflow@google.com +alisher@google.com diff --git a/core/java/android/nfc/tech/OWNERS b/core/java/android/nfc/tech/OWNERS new file mode 100644 index 000000000000..6aaf039244c9 --- /dev/null +++ b/core/java/android/nfc/tech/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 48448 + +zachoverflow@google.com +alisher@google.com diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java index d00c3c361722..74880b2d61d3 100644 --- a/core/java/android/os/BatteryConsumer.java +++ b/core/java/android/os/BatteryConsumer.java @@ -49,6 +49,28 @@ public abstract class BatteryConsumer { public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000; public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999; + /** + * Time usage component, describing the particular part of the system + * that was used for the corresponding amount of time. + * + * @hide + */ + @IntDef(prefix = {"TIME_COMPONENT_"}, value = { + TIME_COMPONENT_CPU, + TIME_COMPONENT_CPU_FOREGROUND, + }) + @Retention(RetentionPolicy.SOURCE) + public static @interface TimeComponent { + } + + public static final int TIME_COMPONENT_CPU = 0; + public static final int TIME_COMPONENT_CPU_FOREGROUND = 1; + + public static final int TIME_COMPONENT_COUNT = 2; + + public static final int FIRST_CUSTOM_TIME_COMPONENT_ID = 1000; + public static final int LAST_CUSTOM_TIME_COMPONENT_ID = 9999; + private final PowerComponents mPowerComponents; protected BatteryConsumer(@NonNull PowerComponents powerComponents) { @@ -83,6 +105,29 @@ public abstract class BatteryConsumer { return mPowerComponents.getConsumedPowerForCustomComponent(componentId); } + /** + * Returns the amount of time since BatteryStats reset used by the specified component, e.g. + * CPU, WiFi etc. + * + * @param componentId The ID of the time component, e.g. + * {@link UidBatteryConsumer#TIME_COMPONENT_CPU}. + * @return Amount of time in milliseconds. + */ + public long getUsageDurationMillis(@TimeComponent int componentId) { + return mPowerComponents.getUsageDurationMillis(componentId); + } + + /** + * Returns the amount of usage time attributed to the specified custom component + * since BatteryStats reset. + * + * @param componentId The ID of the custom power component. + * @return Amount of time in milliseconds. + */ + public long getUsageDurationForCustomComponentMillis(int componentId) { + return mPowerComponents.getUsageDurationForCustomComponentMillis(componentId); + } + protected void writeToParcel(Parcel dest, int flags) { mPowerComponents.writeToParcel(dest, flags); } diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java index 3f036cdcfa72..79f58f68b637 100644 --- a/core/java/android/os/BatteryUsageStats.java +++ b/core/java/android/os/BatteryUsageStats.java @@ -35,7 +35,11 @@ public final class BatteryUsageStats implements Parcelable { private BatteryUsageStats(@NonNull Builder builder) { mConsumedPower = builder.mConsumedPower; mDischargePercentage = builder.mDischargePercentage; - mUidBatteryConsumers = builder.mUidBatteryConsumers; + final int uidBatteryConsumerCount = builder.mUidBatteryConsumerBuilders.size(); + mUidBatteryConsumers = new ArrayList<>(uidBatteryConsumerCount); + for (int i = 0; i < uidBatteryConsumerCount; i++) { + mUidBatteryConsumers.add(builder.mUidBatteryConsumerBuilders.get(i).build()); + } } /** @@ -95,7 +99,8 @@ public final class BatteryUsageStats implements Parcelable { public static final class Builder { private double mConsumedPower; private int mDischargePercentage; - private final ArrayList<UidBatteryConsumer> mUidBatteryConsumers = new ArrayList<>(); + private final ArrayList<UidBatteryConsumer.Builder> mUidBatteryConsumerBuilders = + new ArrayList<>(); /** * Constructs a read-only object using the Builder values. @@ -130,9 +135,15 @@ public final class BatteryUsageStats implements Parcelable { * individual UID. */ @NonNull - public Builder addUidBatteryConsumer(@NonNull UidBatteryConsumer uidBatteryConsumer) { - mUidBatteryConsumers.add(uidBatteryConsumer); + public Builder addUidBatteryConsumerBuilder( + @NonNull UidBatteryConsumer.Builder uidBatteryConsumer) { + mUidBatteryConsumerBuilders.add(uidBatteryConsumer); return this; } + + @NonNull + public List<UidBatteryConsumer.Builder> getUidBatteryConsumerBuilders() { + return mUidBatteryConsumerBuilders; + } } } diff --git a/core/java/android/os/CombinedVibrationEffect.java b/core/java/android/os/CombinedVibrationEffect.java index c9ebc1b7a3c5..7ec7fffd3588 100644 --- a/core/java/android/os/CombinedVibrationEffect.java +++ b/core/java/android/os/CombinedVibrationEffect.java @@ -30,8 +30,6 @@ import java.util.Objects; * Vibrator Vibrators}. * * These effects may be any number of things, from single shot vibrations to complex waveforms. - * - * @hide * @see VibrationEffect */ @SuppressWarnings({"ParcelNotFinal", "ParcelCreator"}) // Parcel only extended here. @@ -94,7 +92,6 @@ public abstract class CombinedVibrationEffect implements Parcelable { /** * A combination of haptic effects that should be played in multiple vibrators in sync. * - * @hide * @see CombinedVibrationEffect#startSynced() */ public static final class SyncedCombination { @@ -144,7 +141,6 @@ public abstract class CombinedVibrationEffect implements Parcelable { /** * A combination of haptic effects that should be played in multiple vibrators in sequence. * - * @hide * @see CombinedVibrationEffect#startSequential() */ public static final class SequentialCombination { diff --git a/core/java/android/os/IVibratorManagerService.aidl b/core/java/android/os/IVibratorManagerService.aidl index 08d201977c49..804dc102c3f6 100644 --- a/core/java/android/os/IVibratorManagerService.aidl +++ b/core/java/android/os/IVibratorManagerService.aidl @@ -18,10 +18,14 @@ package android.os; import android.os.CombinedVibrationEffect; import android.os.VibrationAttributes; +import android.os.VibratorInfo; /** {@hide} */ interface IVibratorManagerService { int[] getVibratorIds(); + VibratorInfo getVibratorInfo(int vibratorId); + boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, + in CombinedVibrationEffect effect, in VibrationAttributes attributes); void vibrate(int uid, String opPkg, in CombinedVibrationEffect effect, in VibrationAttributes attributes, String reason, IBinder token); void cancelVibrate(IBinder token); diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl index 615ae6593330..1cd48dcf797b 100644 --- a/core/java/android/os/IVibratorService.aidl +++ b/core/java/android/os/IVibratorService.aidl @@ -18,6 +18,7 @@ package android.os; import android.os.VibrationEffect; import android.os.VibrationAttributes; +import android.os.VibratorInfo; import android.os.IVibratorStateListener; /** {@hide} */ @@ -25,13 +26,10 @@ interface IVibratorService { boolean hasVibrator(); boolean isVibrating(); + VibratorInfo getVibratorInfo(); boolean registerVibratorStateListener(in IVibratorStateListener listener); boolean unregisterVibratorStateListener(in IVibratorStateListener listener); boolean hasAmplitudeControl(); - int[] areEffectsSupported(in int[] effectIds); - boolean[] arePrimitivesSupported(in int[] primitiveIds); - boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, in VibrationEffect effect, - in VibrationAttributes attributes); void vibrate(int uid, String opPkg, in VibrationEffect effect, in VibrationAttributes attributes, String reason, IBinder token); void cancelVibrate(IBinder token); diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS index 91eb2a502638..a0bcf990fba1 100644 --- a/core/java/android/os/OWNERS +++ b/core/java/android/os/OWNERS @@ -16,7 +16,13 @@ per-file IPowerManager.aidl = michaelwr@google.com, santoscordon@google.com per-file PowerManager.java = michaelwr@google.com, santoscordon@google.com per-file PowerManagerInternal.java = michaelwr@google.com, santoscordon@google.com -# Zygote -per-file ZygoteProcess.java = calin@google.com, chriswailes@google.com, maco@google.com, narayan@google.com, ngeoffray@google.com +# BatteryStats +per-file *BatteryConsumer* = file:/BATTERY_STATS_OWNERS +per-file BatteryManager* = file:/BATTERY_STATS_OWNERS +per-file BatteryStats* = file:/BATTERY_STATS_OWNERS +per-file BatteryUsageStats* = file:/BATTERY_STATS_OWNERS +per-file PowerComponents.java = file:/BATTERY_STATS_OWNERS per-file GraphicsEnvironment.java = chrisforbes@google.com, cnorthrop@google.com, lpy@google.com, timvp@google.com, zzyiwei@google.com + +per-file *Zygote* = file:/ZYGOTE_OWNERS diff --git a/core/java/android/os/ParcelableHolder.java b/core/java/android/os/ParcelableHolder.java index fb9fa109bfa3..1be367c7fca6 100644 --- a/core/java/android/os/ParcelableHolder.java +++ b/core/java/android/os/ParcelableHolder.java @@ -120,31 +120,37 @@ public final class ParcelableHolder implements Parcelable { /** * Write a parcelable into ParcelableHolder, the previous parcelable will be removed. - * @return {@code false} if the parcelable's stability is more unstable ParcelableHolder. + * @throws BadParcelableException if the parcelable's stability is more unstable + * ParcelableHolder. */ - public boolean setParcelable(@Nullable Parcelable p) { - // a ParcelableHolder can only hold things at its stability or higher + public void setParcelable(@Nullable Parcelable p) { + // A ParcelableHolder can only hold things at its stability or higher. if (p != null && this.getStability() > p.getStability()) { - return false; + throw new BadParcelableException( + "A ParcelableHolder can only hold things at its stability or higher. " + + "The ParcelableHolder's stability is " + this.getStability() + + ", but the parcelable's stability is " + p.getStability()); } mParcelable = p; if (mParcel != null) { mParcel.recycle(); mParcel = null; } - return true; } /** * @return the parcelable that was written by {@link #setParcelable} or {@link #readFromParcel}, - * or {@code null} if the parcelable has not been written, or T is different from - * the type written by (@link #setParcelable}. + * or {@code null} if the parcelable has not been written. + * @throws BadParcelableException if T is different from the type written by + * (@link #setParcelable}. */ @Nullable public <T extends Parcelable> T getParcelable(@NonNull Class<T> clazz) { if (mParcel == null) { - if (!clazz.isInstance(mParcelable)) { - return null; + if (mParcelable != null && !clazz.isInstance(mParcelable)) { + throw new BadParcelableException( + "The ParcelableHolder has " + mParcelable.getClass().getName() + + ", but the requested type is " + clazz.getName()); } return (T) mParcelable; } @@ -152,8 +158,10 @@ public final class ParcelableHolder implements Parcelable { mParcel.setDataPosition(0); T parcelable = mParcel.readParcelable(clazz.getClassLoader()); - if (!clazz.isInstance(parcelable)) { - return null; + if (parcelable != null && !clazz.isInstance(parcelable)) { + throw new BadParcelableException( + "The ParcelableHolder has " + parcelable.getClass().getName() + + ", but the requested type is " + clazz.getName()); } mParcelable = parcelable; diff --git a/core/java/android/os/PowerComponents.java b/core/java/android/os/PowerComponents.java index 42ba1ff60e5a..c18fff64ba62 100644 --- a/core/java/android/os/PowerComponents.java +++ b/core/java/android/os/PowerComponents.java @@ -29,21 +29,25 @@ class PowerComponents { private final double mTotalPowerConsumed; private final double[] mPowerComponents; + private final long[] mTimeComponents; PowerComponents(@NonNull Builder builder) { mTotalPowerConsumed = builder.mTotalPowerConsumed; mPowerComponents = builder.mPowerComponents; + mTimeComponents = builder.mTimeComponents; } PowerComponents(@NonNull Parcel source) { mTotalPowerConsumed = source.readDouble(); mPowerComponents = source.createDoubleArray(); + mTimeComponents = source.createLongArray(); } /** Writes contents to Parcel */ void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeDouble(mTotalPowerConsumed); dest.writeDoubleArray(mPowerComponents); + dest.writeLongArray(mTimeComponents); } /** @@ -94,15 +98,58 @@ class PowerComponents { } /** + * Returns the amount of time used by the specified component, e.g. CPU, WiFi etc. + * + * @param componentId The ID of the time component, e.g. + * {@link UidBatteryConsumer#TIME_COMPONENT_CPU}. + * @return Amount of time in milliseconds. + */ + public long getUsageDurationMillis(@UidBatteryConsumer.TimeComponent int componentId) { + if (componentId >= UidBatteryConsumer.TIME_COMPONENT_COUNT) { + throw new IllegalArgumentException( + "Unsupported time component ID: " + componentId); + } + try { + return mTimeComponents[componentId]; + } catch (ArrayIndexOutOfBoundsException e) { + throw new IllegalArgumentException("Unsupported power component ID: " + componentId); + } + } + + /** + * Returns the amount of usage time attributed to the specified custom component. + * + * @param componentId The ID of the custom power component. + * @return Amount of time in milliseconds. + */ + public long getUsageDurationForCustomComponentMillis(int componentId) { + if (componentId < UidBatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID) { + throw new IllegalArgumentException( + "Unsupported custom time component ID: " + componentId); + } + try { + return mTimeComponents[ + UidBatteryConsumer.TIME_COMPONENT_COUNT + componentId + - UidBatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID]; + } catch (ArrayIndexOutOfBoundsException e) { + throw new IllegalArgumentException( + "Unsupported custom time component ID: " + componentId); + } + } + + /** * Builder for PowerComponents. */ static final class Builder { private double mTotalPowerConsumed; private final double[] mPowerComponents; + private final long[] mTimeComponents; - Builder(int customPowerComponentCount) { - mPowerComponents = new double[BatteryConsumer.POWER_COMPONENT_COUNT + Builder(int customPowerComponentCount, int customTimeComponentCount) { + mPowerComponents = new double[UidBatteryConsumer.POWER_COMPONENT_COUNT + customPowerComponentCount]; + mTimeComponents = new long[UidBatteryConsumer.TIME_COMPONENT_COUNT + + customTimeComponentCount]; } /** @@ -160,6 +207,53 @@ class PowerComponents { } /** + * Sets the amount of time used by the specified component, e.g. CPU, WiFi etc. + * + * @param componentId The ID of the time component, e.g. + * {@link UidBatteryConsumer#TIME_COMPONENT_CPU}. + * @param componentUsageDurationMillis Amount of time in milliseconds. + */ + @NonNull + public Builder setUsageDurationMillis(@UidBatteryConsumer.TimeComponent int componentId, + long componentUsageDurationMillis) { + if (componentId >= UidBatteryConsumer.TIME_COMPONENT_COUNT) { + throw new IllegalArgumentException( + "Unsupported time component ID: " + componentId); + } + try { + mTimeComponents[componentId] = componentUsageDurationMillis; + } catch (ArrayIndexOutOfBoundsException e) { + throw new IllegalArgumentException( + "Unsupported time component ID: " + componentId); + } + return this; + } + + /** + * Sets the amount of time used by the specified custom component. + * + * @param componentId The ID of the custom power component. + * @param componentUsageDurationMillis Amount of time in milliseconds. + */ + @NonNull + public Builder setUsageDurationForCustomComponentMillis(int componentId, + long componentUsageDurationMillis) { + if (componentId < UidBatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID) { + throw new IllegalArgumentException( + "Unsupported custom time component ID: " + componentId); + } + try { + mTimeComponents[UidBatteryConsumer.TIME_COMPONENT_COUNT + componentId + - UidBatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID] = + componentUsageDurationMillis; + } catch (ArrayIndexOutOfBoundsException e) { + throw new IllegalArgumentException( + "Unsupported custom time component ID: " + componentId); + } + return this; + } + + /** * Creates a read-only object out of the Builder values. */ @NonNull diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java index 5c9067ac3c3e..0330500f0997 100644 --- a/core/java/android/os/SystemVibrator.java +++ b/core/java/android/os/SystemVibrator.java @@ -18,6 +18,7 @@ package android.os; import android.annotation.CallbackExecutor; import android.annotation.NonNull; +import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.media.AudioAttributes; @@ -38,8 +39,12 @@ public class SystemVibrator extends Vibrator { private static final String TAG = "Vibrator"; private final IVibratorService mService; + private final IVibratorManagerService mManagerService; + private final Object mLock = new Object(); private final Binder mToken = new Binder(); private final Context mContext; + @GuardedBy("mLock") + private VibratorInfo mVibratorInfo; @GuardedBy("mDelegates") private final ArrayMap<OnVibratorStateChangedListener, @@ -49,6 +54,8 @@ public class SystemVibrator extends Vibrator { public SystemVibrator() { mContext = null; mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator")); + mManagerService = IVibratorManagerService.Stub.asInterface( + ServiceManager.getService("vibrator_manager")); } @UnsupportedAppUsage @@ -56,6 +63,8 @@ public class SystemVibrator extends Vibrator { super(context); mContext = context; mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator")); + mManagerService = IVibratorManagerService.Stub.asInterface( + ServiceManager.getService("vibrator_manager")); } @Override @@ -207,13 +216,14 @@ public class SystemVibrator extends Vibrator { @Override public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, VibrationEffect effect, AudioAttributes attributes) { - if (mService == null) { + if (mManagerService == null) { Log.w(TAG, "Failed to set always-on effect; no vibrator service."); return false; } try { VibrationAttributes atr = new VibrationAttributes.Builder(attributes, effect).build(); - return mService.setAlwaysOnEffect(uid, opPkg, alwaysOnId, effect, atr); + CombinedVibrationEffect combinedEffect = CombinedVibrationEffect.createSynced(effect); + return mManagerService.setAlwaysOnEffect(uid, opPkg, alwaysOnId, combinedEffect, atr); } catch (RemoteException e) { Log.w(TAG, "Failed to set always-on effect.", e); } @@ -236,26 +246,28 @@ public class SystemVibrator extends Vibrator { @Override public int[] areEffectsSupported(@VibrationEffect.EffectType int... effectIds) { - try { - return mService.areEffectsSupported(effectIds); - } catch (RemoteException e) { - Log.w(TAG, "Failed to query effect support"); - throw e.rethrowAsRuntimeException(); + VibratorInfo vibratorInfo = getVibratorInfo(); + int[] supported = new int[effectIds.length]; + for (int i = 0; i < effectIds.length; i++) { + supported[i] = vibratorInfo == null + ? Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN + : vibratorInfo.isEffectSupported(effectIds[i]); } + return supported; } @Override public boolean[] arePrimitivesSupported( @NonNull @VibrationEffect.Composition.Primitive int... primitiveIds) { - try { - return mService.arePrimitivesSupported(primitiveIds); - } catch (RemoteException e) { - Log.w(TAG, "Failed to query effect support"); - throw e.rethrowAsRuntimeException(); + VibratorInfo vibratorInfo = getVibratorInfo(); + boolean[] supported = new boolean[primitiveIds.length]; + for (int i = 0; i < primitiveIds.length; i++) { + supported[i] = vibratorInfo == null + ? false : vibratorInfo.isPrimitiveSupported(primitiveIds[i]); } + return supported; } - @Override public void cancel() { if (mService == null) { @@ -267,4 +279,22 @@ public class SystemVibrator extends Vibrator { Log.w(TAG, "Failed to cancel vibration.", e); } } + + @Nullable + private VibratorInfo getVibratorInfo() { + try { + synchronized (mLock) { + if (mVibratorInfo != null) { + return mVibratorInfo; + } + if (mService == null) { + return null; + } + return mVibratorInfo = mService.getVibratorInfo(); + } + } catch (RemoteException e) { + Log.w(TAG, "Failed to query vibrator info"); + throw e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java index 7dcbf7d4cef3..d12ccb57794b 100644 --- a/core/java/android/os/UidBatteryConsumer.java +++ b/core/java/android/os/UidBatteryConsumer.java @@ -82,12 +82,24 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela */ public static final class Builder { private final PowerComponents.Builder mPowerComponentsBuilder; + private final BatteryStats.Uid mBatteryStatsUid; private final int mUid; private String mPackageWithHighestDrain; - public Builder(int customPowerComponentCount, int uid) { - mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentCount); - mUid = uid; + public Builder(int customPowerComponentCount, int customTimeComponentCount, + BatteryStats.Uid batteryStatsUid) { + mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentCount, + customTimeComponentCount); + mBatteryStatsUid = batteryStatsUid; + mUid = batteryStatsUid.getUid(); + } + + public BatteryStats.Uid getBatteryStatsUid() { + return mBatteryStatsUid; + } + + public int getUid() { + return mUid; } /** @@ -102,7 +114,7 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela * Sets the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc. * * @param componentId The ID of the power component, e.g. - * {@link BatteryConsumer#POWER_COMPONENT_CPU}. + * {@link BatteryConsumer#POWER_COMPONENT_CPU}. * @param componentPower Amount of consumed power in mAh. */ @NonNull @@ -133,6 +145,35 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela } /** + * Sets the amount of time used by the specified component, e.g. CPU, WiFi etc. + * + * @param componentId The ID of the time component, e.g. + * {@link UidBatteryConsumer#TIME_COMPONENT_CPU}. + * @param componentUsageDurationMillis Amount of time in milliseconds. + */ + @NonNull + public Builder setUsageDurationMillis(@UidBatteryConsumer.TimeComponent int componentId, + long componentUsageDurationMillis) { + mPowerComponentsBuilder.setUsageDurationMillis(componentId, + componentUsageDurationMillis); + return this; + } + + /** + * Sets the amount of time used by the specified custom component. + * + * @param componentId The ID of the custom power component. + * @param componentUsageDurationMillis Amount of time in milliseconds. + */ + @NonNull + public Builder setUsageDurationForCustomComponentMillis(int componentId, + long componentUsageDurationMillis) { + mPowerComponentsBuilder.setUsageDurationForCustomComponentMillis(componentId, + componentUsageDurationMillis); + return this; + } + + /** * Sets the name of the package owned by this UID that consumed the highest amount * of power since BatteryStats reset. */ diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java index d6720248720a..7e50ebc419dd 100644 --- a/core/java/android/os/UserHandle.java +++ b/core/java/android/os/UserHandle.java @@ -223,6 +223,14 @@ public final class UserHandle implements Parcelable { } /** + * Whether a UID belongs to a shared app gid. + * @hide + */ + public static boolean isSharedAppGid(int uid) { + return getAppIdFromSharedAppGid(uid) != -1; + } + + /** * Returns the user for a given uid. * @param uid A uid for an application running in a particular user. * @return A {@link UserHandle} for that user. diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index aba1f281c583..e7d19c5eb18a 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -136,6 +136,12 @@ public class UserManager { public static final String USER_TYPE_PROFILE_MANAGED = "android.os.usertype.profile.MANAGED"; /** + * User type representing a generic profile for testing purposes. Only on debuggable builds. + * @hide + */ + public static final String USER_TYPE_PROFILE_TEST = "android.os.usertype.profile.TEST"; + + /** * User type representing a {@link UserHandle#USER_SYSTEM system} user that is <b>not</b> a * human user. * This type of user cannot be created; it can only pre-exist on first boot. diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index f76eb86f0fca..b57418d751bc 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -477,6 +477,28 @@ public abstract class VibrationEffect implements Parcelable { } /** @hide */ + public static String effectIdToString(int effectId) { + switch (effectId) { + case EFFECT_CLICK: + return "CLICK"; + case EFFECT_TICK: + return "TICK"; + case EFFECT_HEAVY_CLICK: + return "HEAVY_CLICK"; + case EFFECT_DOUBLE_CLICK: + return "DOUBLE_CLICK"; + case EFFECT_POP: + return "POP"; + case EFFECT_THUD: + return "THUD"; + case EFFECT_TEXTURE_TICK: + return "TEXTURE_TICK"; + default: + return Integer.toString(effectId); + } + } + + /** @hide */ @TestApi public static class OneShot extends VibrationEffect implements Parcelable { private final long mDuration; @@ -1201,10 +1223,8 @@ public abstract class VibrationEffect implements Parcelable { return "PRIMITIVE_QUICK_FALL"; case PRIMITIVE_TICK: return "PRIMITIVE_TICK"; - default: return Integer.toString(id); - } } diff --git a/apex/statsd/tests/libstatspull/protos/test_atoms.proto b/core/java/android/os/VibratorInfo.aidl index 56c1b534a7ce..9a7cb1303b93 100644 --- a/apex/statsd/tests/libstatspull/protos/test_atoms.proto +++ b/core/java/android/os/VibratorInfo.aidl @@ -13,20 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -syntax = "proto2"; - -package com.android.internal.os.statsd.protos; - -option java_package = "com.android.internal.os.statsd.protos"; -option java_outer_classname = "TestAtoms"; - -message PullCallbackAtomWrapper { - optional PullCallbackAtom pull_callback_atom = 150030; -} - -message PullCallbackAtom { - optional int64 long_val = 1; -} - +package android.os; +parcelable VibratorInfo; diff --git a/core/java/android/os/VibratorInfo.java b/core/java/android/os/VibratorInfo.java new file mode 100644 index 000000000000..07272e756e77 --- /dev/null +++ b/core/java/android/os/VibratorInfo.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.util.SparseBooleanArray; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +/** + * A VibratorInfo describes the capabilities of a {@link Vibrator}. + * + * This description includes its capabilities, list of supported effects and composition primitives. + * + * @hide + */ +public final class VibratorInfo implements Parcelable { + + /** + * Capability to set amplitude values to vibrations. + * @hide + */ + // Internally this maps to the HAL constant IVibrator::CAP_AMPLITUDE_CONTROL + public static final int CAPABILITY_AMPLITUDE_CONTROL = 4; + + /** + * Capability to compose primitives into a single effect. + * @hide + */ + // Internally this maps to the HAL constant IVibrator::CAP_COMPOSE_EFFECTS + public static final int CAPABILITY_COMPOSE_EFFECTS = 32; + + private final int mId; + private final long mCapabilities; + @Nullable + private final SparseBooleanArray mSupportedEffects; + @Nullable + private final SparseBooleanArray mSupportedPrimitives; + + VibratorInfo(Parcel in) { + mId = in.readInt(); + mCapabilities = in.readLong(); + mSupportedEffects = in.readSparseBooleanArray(); + mSupportedPrimitives = in.readSparseBooleanArray(); + } + + /** @hide */ + public VibratorInfo(int id, long capabilities, int[] supportedEffects, + int[] supportedPrimitives) { + mId = id; + mCapabilities = capabilities; + mSupportedEffects = toSparseBooleanArray(supportedEffects); + mSupportedPrimitives = toSparseBooleanArray(supportedPrimitives); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mId); + dest.writeLong(mCapabilities); + dest.writeSparseBooleanArray(mSupportedEffects); + dest.writeSparseBooleanArray(mSupportedPrimitives); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof VibratorInfo)) { + return false; + } + VibratorInfo that = (VibratorInfo) o; + return mId == that.mId && mCapabilities == that.mCapabilities + && Objects.equals(mSupportedEffects, that.mSupportedEffects) + && Objects.equals(mSupportedPrimitives, that.mSupportedPrimitives); + } + + @Override + public int hashCode() { + return Objects.hash(mId, mCapabilities, mSupportedEffects, mSupportedPrimitives); + } + + @Override + public String toString() { + return "VibratorInfo{" + + "mId=" + mId + + ", mCapabilities=" + Arrays.toString(getCapabilitiesNames()) + + ", mCapabilities flags=" + mCapabilities + + ", mSupportedEffects=" + Arrays.toString(getSupportedEffectsNames()) + + ", mSupportedPrimitives=" + Arrays.toString(getSupportedPrimitivesNames()) + + '}'; + } + + /** Return the id of this vibrator. */ + public int getId() { + return mId; + } + + /** + * Check whether the vibrator has amplitude control. + * + * @return True if the hardware can control the amplitude of the vibrations, otherwise false. + */ + public boolean hasAmplitudeControl() { + return hasCapability(CAPABILITY_AMPLITUDE_CONTROL); + } + + /** + * Query whether the vibrator supports the given effect. + * + * @param effectId Which effects to query for. + * @return {@link Vibrator#VIBRATION_EFFECT_SUPPORT_YES} if the effect is supported, + * {@link Vibrator#VIBRATION_EFFECT_SUPPORT_NO} if it isn't supported, or + * {@link Vibrator#VIBRATION_EFFECT_SUPPORT_UNKNOWN} if the system can't determine whether it's + * supported or not. + */ + @Vibrator.VibrationEffectSupport + public int isEffectSupported(@VibrationEffect.EffectType int effectId) { + if (mSupportedEffects == null) { + return Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN; + } + return mSupportedEffects.get(effectId, false) ? Vibrator.VIBRATION_EFFECT_SUPPORT_YES + : Vibrator.VIBRATION_EFFECT_SUPPORT_NO; + } + + /** + * Query whether the vibrator supports the given primitive. + * + * @param primitiveId Which primitives to query for. + * @return Whether the primitive is supported. + */ + public boolean isPrimitiveSupported(@VibrationEffect.Composition.Primitive int primitiveId) { + return hasCapability(CAPABILITY_COMPOSE_EFFECTS) && mSupportedPrimitives != null + && mSupportedPrimitives.get(primitiveId, false); + } + + /** + * Check against this vibrator capabilities. + * + * @param capability one of IVibrator.CAP_* + * @return true if this vibrator has this capability, false otherwise + * @hide + */ + public boolean hasCapability(long capability) { + return (mCapabilities & capability) == capability; + } + + private String[] getCapabilitiesNames() { + List<String> names = new ArrayList<>(); + if (hasCapability(CAPABILITY_AMPLITUDE_CONTROL)) { + names.add("AMPLITUDE_CONTROL"); + } + if (hasCapability(CAPABILITY_COMPOSE_EFFECTS)) { + names.add("COMPOSE_EFFECTS"); + } + return names.toArray(new String[names.size()]); + } + + private String[] getSupportedEffectsNames() { + if (mSupportedEffects == null) { + return new String[0]; + } + String[] names = new String[mSupportedEffects.size()]; + for (int i = 0; i < mSupportedEffects.size(); i++) { + names[i] = VibrationEffect.effectIdToString(mSupportedEffects.keyAt(i)); + } + return names; + } + + private String[] getSupportedPrimitivesNames() { + if (mSupportedPrimitives == null) { + return new String[0]; + } + String[] names = new String[mSupportedPrimitives.size()]; + for (int i = 0; i < mSupportedPrimitives.size(); i++) { + names[i] = VibrationEffect.Composition.primitiveToString(mSupportedPrimitives.keyAt(i)); + } + return names; + } + + @Nullable + private static SparseBooleanArray toSparseBooleanArray(int[] values) { + if (values == null) { + return null; + } + SparseBooleanArray array = new SparseBooleanArray(); + for (int value : values) { + array.put(value, true); + } + return array; + } + + @NonNull + public static final Creator<VibratorInfo> CREATOR = + new Creator<VibratorInfo>() { + @Override + public VibratorInfo createFromParcel(Parcel in) { + return new VibratorInfo(in); + } + + @Override + public VibratorInfo[] newArray(int size) { + return new VibratorInfo[size]; + } + }; +} diff --git a/core/java/android/os/VibratorManager.java b/core/java/android/os/VibratorManager.java new file mode 100644 index 000000000000..1d5a58745279 --- /dev/null +++ b/core/java/android/os/VibratorManager.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +import android.annotation.NonNull; + +/** + * VibratorManager provides access to multiple vibrators, as well as the ability to run them in + * a synchronized fashion. + */ +public abstract class VibratorManager { + /** @hide */ + protected static final String TAG = "VibratorManager"; + + /** + * {@hide} + */ + public VibratorManager() { + } + + /** + * This method lists all available actuator ids, returning a possible empty list. + * If the device has only a single actuator, this should return a single entry with a + * default id. + */ + @NonNull + public abstract int[] getVibratorIds(); + + /** + * Returns a Vibrator service for given id. + * This allows users to perform a vibration effect on a single actuator. + */ + @NonNull + public abstract Vibrator getVibrator(int vibratorId); + + /** + * Returns the system default Vibrator service. + */ + @NonNull + public abstract Vibrator getDefaultVibrator(); + + /** + * Vibrates all actuators by passing each VibrationEffect within CombinedVibrationEffect + * to the respective actuator, in sync. + */ + public abstract void vibrate(@NonNull CombinedVibrationEffect effect); +} diff --git a/core/java/android/os/connectivity/OWNERS b/core/java/android/os/connectivity/OWNERS new file mode 100644 index 000000000000..a0f023814f9b --- /dev/null +++ b/core/java/android/os/connectivity/OWNERS @@ -0,0 +1 @@ +dplotnikov@google.com diff --git a/core/java/android/os/health/OWNERS b/core/java/android/os/health/OWNERS new file mode 100644 index 000000000000..6045344126c0 --- /dev/null +++ b/core/java/android/os/health/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 26805 + +dplotnikov@google.com +mwachens@google.com diff --git a/core/java/android/os/image/OWNERS b/core/java/android/os/image/OWNERS new file mode 100644 index 000000000000..389b55bcf96e --- /dev/null +++ b/core/java/android/os/image/OWNERS @@ -0,0 +1 @@ +andrewhsieh@google.com diff --git a/core/java/android/os/storage/OWNERS b/core/java/android/os/storage/OWNERS new file mode 100644 index 000000000000..8af7de597294 --- /dev/null +++ b/core/java/android/os/storage/OWNERS @@ -0,0 +1,7 @@ +# Bug component: 95221 + +narayan@google.com +nandana@google.com +corinac@google.com +zezeozue@google.com +maco@google.com diff --git a/core/java/android/permission/OWNERS b/core/java/android/permission/OWNERS new file mode 100644 index 000000000000..d09f351bdfd1 --- /dev/null +++ b/core/java/android/permission/OWNERS @@ -0,0 +1,8 @@ +# Bug component: 137825 + +moltmann@google.com +evanseverson@google.com +ntmyren@google.com +zhanghai@google.com +svetoslavganov@android.com +svetoslavganov@google.com diff --git a/core/java/android/permissionpresenterservice/OWNERS b/core/java/android/permissionpresenterservice/OWNERS new file mode 100644 index 000000000000..d09f351bdfd1 --- /dev/null +++ b/core/java/android/permissionpresenterservice/OWNERS @@ -0,0 +1,8 @@ +# Bug component: 137825 + +moltmann@google.com +evanseverson@google.com +ntmyren@google.com +zhanghai@google.com +svetoslavganov@android.com +svetoslavganov@google.com diff --git a/core/java/android/print/OWNERS b/core/java/android/print/OWNERS new file mode 100644 index 000000000000..72f09832becf --- /dev/null +++ b/core/java/android/print/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 47273 + +moltmann@google.com +svetoslavganov@android.com +svetoslavganov@google.com diff --git a/core/java/android/print/pdf/OWNERS b/core/java/android/print/pdf/OWNERS new file mode 100644 index 000000000000..72f09832becf --- /dev/null +++ b/core/java/android/print/pdf/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 47273 + +moltmann@google.com +svetoslavganov@android.com +svetoslavganov@google.com diff --git a/core/java/android/printservice/OWNERS b/core/java/android/printservice/OWNERS new file mode 100644 index 000000000000..72f09832becf --- /dev/null +++ b/core/java/android/printservice/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 47273 + +moltmann@google.com +svetoslavganov@android.com +svetoslavganov@google.com diff --git a/core/java/android/printservice/recommendation/OWNERS b/core/java/android/printservice/recommendation/OWNERS new file mode 100644 index 000000000000..72f09832becf --- /dev/null +++ b/core/java/android/printservice/recommendation/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 47273 + +moltmann@google.com +svetoslavganov@android.com +svetoslavganov@google.com diff --git a/core/java/android/provider/OWNERS b/core/java/android/provider/OWNERS index 97e015646df0..792ff20f6d28 100644 --- a/core/java/android/provider/OWNERS +++ b/core/java/android/provider/OWNERS @@ -2,4 +2,8 @@ per-file DeviceConfig.java = svetoslavganov@google.com per-file DeviceConfig.java = hackbod@google.com per-file DeviceConfig.java = schfan@google.com - +per-file CallLog.java = file:/telephony/OWNERS +per-file DocumentsContract.java = file:/core/java/android/os/storage/OWNERS +per-file DocumentsProvider.java = file:/core/java/android/os/storage/OWNERS +per-file MediaStore.java = file:/core/java/android/os/storage/OWNERS +per-file Telephony.java = file:/telephony/OWNERS diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 12791bcc194b..27f753007201 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3060,6 +3060,7 @@ public final class Settings { // com.android.providers.settings.SettingsProtoDumpUtil#dumpProtoSystemSettingsLocked. private static final float DEFAULT_FONT_SCALE = 1.0f; + private static final int DEFAULT_FONT_WEIGHT = 0; /** * The content:// style URL for this table @@ -3581,9 +3582,7 @@ public final class Settings { outConfig.fontScale = DEFAULT_FONT_SCALE; } outConfig.fontWeightAdjustment = Settings.Secure.getIntForUser( - cr, Settings.Secure.FONT_WEIGHT_ADJUSTMENT, - Configuration.FONT_WEIGHT_ADJUSTMENT_UNDEFINED, - userHandle); + cr, Settings.Secure.FONT_WEIGHT_ADJUSTMENT, DEFAULT_FONT_WEIGHT, userHandle); final String localeValue = Settings.System.getStringForUser(cr, SYSTEM_LOCALES, userHandle); @@ -14484,10 +14483,11 @@ public final class Settings { public static final String SHOW_PEOPLE_SPACE = "show_people_space"; /** - * Which types of conversations to show in People Space. + * Which types of conversation(s) to show in People Space. * Values are: - * 0: All conversations (default) + * 0: Single user-selected conversation (default) * 1: Priority conversations only + * 2: All conversations * @hide */ public static final String PEOPLE_SPACE_CONVERSATION_TYPE = diff --git a/core/java/android/se/OWNERS b/core/java/android/se/OWNERS new file mode 100644 index 000000000000..f1539dc55d59 --- /dev/null +++ b/core/java/android/se/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 456592 + +cbrubaker@google.com +vishwath@google.com diff --git a/core/java/android/se/omapi/OWNERS b/core/java/android/se/omapi/OWNERS new file mode 100644 index 000000000000..f1539dc55d59 --- /dev/null +++ b/core/java/android/se/omapi/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 456592 + +cbrubaker@google.com +vishwath@google.com diff --git a/core/java/android/security/OWNERS b/core/java/android/security/OWNERS index 7120376e31d2..3f8d75e6118d 100644 --- a/core/java/android/security/OWNERS +++ b/core/java/android/security/OWNERS @@ -1,3 +1,8 @@ +# Bug component: 36824 + +cbrubaker@google.com +vishwath@google.com + per-file NetworkSecurityPolicy.java = cbrubaker@google.com per-file NetworkSecurityPolicy.java = klyubin@google.com per-file FrameworkNetworkSecurityPolicy.java = cbrubaker@google.com diff --git a/core/java/android/security/keymaster/OWNERS b/core/java/android/security/keymaster/OWNERS new file mode 100644 index 000000000000..65129a46d113 --- /dev/null +++ b/core/java/android/security/keymaster/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 189335 + +swillden@google.com +jdanis@google.com +jbires@google.com diff --git a/core/java/android/security/keystore/OWNERS b/core/java/android/security/keystore/OWNERS index bb487fb52c9f..65129a46d113 100644 --- a/core/java/android/security/keystore/OWNERS +++ b/core/java/android/security/keystore/OWNERS @@ -1,4 +1,5 @@ -aseemk@google.com -bozhu@google.com -dementyev@google.com -robertberry@google.com +# Bug component: 189335 + +swillden@google.com +jdanis@google.com +jbires@google.com diff --git a/core/java/android/security/keystore/recovery/OWNERS b/core/java/android/security/keystore/recovery/OWNERS new file mode 100644 index 000000000000..65129a46d113 --- /dev/null +++ b/core/java/android/security/keystore/recovery/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 189335 + +swillden@google.com +jdanis@google.com +jbires@google.com diff --git a/core/java/android/security/net/OWNERS b/core/java/android/security/net/OWNERS new file mode 100644 index 000000000000..d8281645738b --- /dev/null +++ b/core/java/android/security/net/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 36824 + +cbrubaker@google.com +brambonne@google.com diff --git a/core/java/android/security/net/config/OWNERS b/core/java/android/security/net/config/OWNERS index 53503734e0a7..85ce3c63f18b 100644 --- a/core/java/android/security/net/config/OWNERS +++ b/core/java/android/security/net/config/OWNERS @@ -1,3 +1,5 @@ +# Bug component: 36824 set noparent + cbrubaker@google.com -klyubin@google.com +brambonne@google.com diff --git a/core/java/android/service/appprediction/OWNERS b/core/java/android/service/appprediction/OWNERS new file mode 100644 index 000000000000..fe012da8e307 --- /dev/null +++ b/core/java/android/service/appprediction/OWNERS @@ -0,0 +1,2 @@ +adamcohen@google.com +sunnygoyal@google.com diff --git a/core/java/android/service/attention/OWNERS b/core/java/android/service/attention/OWNERS new file mode 100644 index 000000000000..dd579b6eb6dc --- /dev/null +++ b/core/java/android/service/attention/OWNERS @@ -0,0 +1 @@ +asalo@google.com diff --git a/core/java/android/service/autofill/OWNERS b/core/java/android/service/autofill/OWNERS new file mode 100644 index 000000000000..a08863276da7 --- /dev/null +++ b/core/java/android/service/autofill/OWNERS @@ -0,0 +1,9 @@ +# Bug component: 351486 + +joannechung@google.com +adamhe@google.com +tymtsai@google.com +lpeter@google.com +augale@google.com +svetoslavganov@android.com +svetoslavganov@google.com diff --git a/core/java/android/service/autofill/augmented/OWNERS b/core/java/android/service/autofill/augmented/OWNERS new file mode 100644 index 000000000000..a08863276da7 --- /dev/null +++ b/core/java/android/service/autofill/augmented/OWNERS @@ -0,0 +1,9 @@ +# Bug component: 351486 + +joannechung@google.com +adamhe@google.com +tymtsai@google.com +lpeter@google.com +augale@google.com +svetoslavganov@android.com +svetoslavganov@google.com diff --git a/core/java/android/service/carrier/OWNERS b/core/java/android/service/carrier/OWNERS new file mode 100644 index 000000000000..d768ef476206 --- /dev/null +++ b/core/java/android/service/carrier/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +fionaxu@google.com diff --git a/core/java/android/service/chooser/OWNERS b/core/java/android/service/chooser/OWNERS new file mode 100644 index 000000000000..a5acba58b52c --- /dev/null +++ b/core/java/android/service/chooser/OWNERS @@ -0,0 +1,4 @@ +asc@google.com +mpietal@google.com +dsandler@android.com +dsandler@google.com diff --git a/core/java/android/service/contentcapture/OWNERS b/core/java/android/service/contentcapture/OWNERS new file mode 100644 index 000000000000..6337327cec25 --- /dev/null +++ b/core/java/android/service/contentcapture/OWNERS @@ -0,0 +1,9 @@ +# Bug component: 544200 + +joannechung@google.com +adamhe@google.com +tymtsai@google.com +lpeter@google.com +augale@google.com +svetoslavganov@android.com +svetoslavganov@google.com diff --git a/core/java/android/service/contentsuggestions/OWNERS b/core/java/android/service/contentsuggestions/OWNERS new file mode 100644 index 000000000000..46b5ea03c545 --- /dev/null +++ b/core/java/android/service/contentsuggestions/OWNERS @@ -0,0 +1,7 @@ +joannechung@google.com +adamhe@google.com +tymtsai@google.com +lpeter@google.com +augale@google.com +svetoslavganov@android.com +svetoslavganov@google.com diff --git a/core/java/android/service/dreams/OWNERS b/core/java/android/service/dreams/OWNERS index 708ab4c4ba79..f8318054ddfc 100644 --- a/core/java/android/service/dreams/OWNERS +++ b/core/java/android/service/dreams/OWNERS @@ -1,4 +1,3 @@ -dsandler@android.com -michaelwr@google.com -roosa@google.com -galinap@google.com +# Bug component: 78010 + +dsandler@google.com diff --git a/core/java/android/service/gatekeeper/OWNERS b/core/java/android/service/gatekeeper/OWNERS new file mode 100644 index 000000000000..2ca52cdc0495 --- /dev/null +++ b/core/java/android/service/gatekeeper/OWNERS @@ -0,0 +1,3 @@ +swillden@google.com +jdanis@google.com +jbires@google.com diff --git a/core/java/android/service/media/OWNERS b/core/java/android/service/media/OWNERS new file mode 100644 index 000000000000..916fc36ffbc6 --- /dev/null +++ b/core/java/android/service/media/OWNERS @@ -0,0 +1,8 @@ +# Bug component: 137631 + +hdmoon@google.com +insun@google.com +jaewan@google.com +jinpark@google.com +klhyun@google.com +gyumin@google.com diff --git a/core/java/android/service/notification/OWNERS b/core/java/android/service/notification/OWNERS index 2e94be5bf329..debb493c46c7 100644 --- a/core/java/android/service/notification/OWNERS +++ b/core/java/android/service/notification/OWNERS @@ -1,4 +1,6 @@ +# Bug component: 34005 + juliacr@google.com -beverlyt@google.com +pixel@google.com dsandler@android.com -pixel@google.com
\ No newline at end of file +dsandler@google.com diff --git a/core/java/android/service/quicksettings/OWNERS b/core/java/android/service/quicksettings/OWNERS new file mode 100644 index 000000000000..12eb7c7754c7 --- /dev/null +++ b/core/java/android/service/quicksettings/OWNERS @@ -0,0 +1,6 @@ +# Bug component: 78010 + +kozynski@google.com +pixel@google.com +dsandler@android.com +dsandler@google.com diff --git a/core/java/android/service/resolver/OWNERS b/core/java/android/service/resolver/OWNERS new file mode 100644 index 000000000000..10150c3709e6 --- /dev/null +++ b/core/java/android/service/resolver/OWNERS @@ -0,0 +1,6 @@ +# Bug component: 78010 + +asc@google.com +mpietal@google.com +dsandler@android.com +dsandler@google.com diff --git a/core/java/android/service/restrictions/OWNERS b/core/java/android/service/restrictions/OWNERS new file mode 100644 index 000000000000..eaba2e92181a --- /dev/null +++ b/core/java/android/service/restrictions/OWNERS @@ -0,0 +1 @@ +yamasani@google.com diff --git a/core/java/android/service/textclassifier/OWNERS b/core/java/android/service/textclassifier/OWNERS new file mode 100644 index 000000000000..a535f5258732 --- /dev/null +++ b/core/java/android/service/textclassifier/OWNERS @@ -0,0 +1,9 @@ +# Bug component: 709498 + +joannechung@google.com +adamhe@google.com +tymtsai@google.com +lpeter@google.com +augale@google.com +svetoslavganov@android.com +svetoslavganov@google.com diff --git a/core/java/android/service/textservice/OWNERS b/core/java/android/service/textservice/OWNERS new file mode 100644 index 000000000000..a637754ba17a --- /dev/null +++ b/core/java/android/service/textservice/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 34867 + +ogunwale@google.com +roosa@google.com +yukawa@google.com diff --git a/core/java/android/service/trust/OWNERS b/core/java/android/service/trust/OWNERS new file mode 100644 index 000000000000..affe471e7770 --- /dev/null +++ b/core/java/android/service/trust/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 36824 + +cbrubaker@google.com +vishwath@google.com diff --git a/core/java/android/service/voice/OWNERS b/core/java/android/service/voice/OWNERS new file mode 100644 index 000000000000..46b5ea03c545 --- /dev/null +++ b/core/java/android/service/voice/OWNERS @@ -0,0 +1,7 @@ +joannechung@google.com +adamhe@google.com +tymtsai@google.com +lpeter@google.com +augale@google.com +svetoslavganov@android.com +svetoslavganov@google.com diff --git a/core/java/android/service/wallpaper/OWNERS b/core/java/android/service/wallpaper/OWNERS new file mode 100644 index 000000000000..756eef8de220 --- /dev/null +++ b/core/java/android/service/wallpaper/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 78010 + +dupin@google.com +dsandler@android.com +dsandler@google.com diff --git a/core/java/android/service/watchdog/OWNERS b/core/java/android/service/watchdog/OWNERS new file mode 100644 index 000000000000..1c045e10c0ec --- /dev/null +++ b/core/java/android/service/watchdog/OWNERS @@ -0,0 +1,3 @@ +narayan@google.com +nandana@google.com +olilan@google.com diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index cc3284a1f885..a9548b0a42b4 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -786,6 +786,21 @@ public class TelephonyRegistryManager { } } + /** + * Notify that the data enabled has changed. + * + * @param enabled True if data is enabled, otherwise disabled. + * @param reason Reason for data enabled/disabled. See {@code REASON_*} in + * {@link TelephonyManager}. + */ + public void notifyDataEnabled(boolean enabled, @TelephonyManager.DataEnabledReason int reason) { + try { + sRegistry.notifyDataEnabled(enabled, reason); + } catch (RemoteException ex) { + // system server crash + } + } + public @NonNull Set<Integer> getEventsFromListener(@NonNull PhoneStateListener listener) { Set<Integer> eventList = new ArraySet<>(); diff --git a/core/java/android/timezone/OWNERS b/core/java/android/timezone/OWNERS new file mode 100644 index 000000000000..09447a971bdd --- /dev/null +++ b/core/java/android/timezone/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/timezone/OWNERS diff --git a/core/java/android/transition/OWNERS b/core/java/android/transition/OWNERS new file mode 100644 index 000000000000..eb5a58115a8f --- /dev/null +++ b/core/java/android/transition/OWNERS @@ -0,0 +1,6 @@ +# Bug component: 25700 + +romainguy@google.com +mount@google.com +alanv@google.com +adamp@google.com diff --git a/core/java/android/util/TypedXmlPullParser.java b/core/java/android/util/TypedXmlPullParser.java index b3b51b54e651..aa68bf42fe52 100644 --- a/core/java/android/util/TypedXmlPullParser.java +++ b/core/java/android/util/TypedXmlPullParser.java @@ -30,67 +30,168 @@ import org.xmlpull.v1.XmlPullParserException; */ public interface TypedXmlPullParser extends XmlPullParser { /** + * @return index of requested attribute, otherwise {@code -1} if undefined + */ + default int getAttributeIndex(@Nullable String namespace, @NonNull String name) { + final boolean namespaceNull = (namespace == null); + final int count = getAttributeCount(); + for (int i = 0; i < count; i++) { + if ((namespaceNull || namespace.equals(getAttributeNamespace(i))) + && name.equals(getAttributeName(i))) { + return i; + } + } + return -1; + } + + /** + * @return index of requested attribute + * @throws XmlPullParserException if the value is undefined + */ + default int getAttributeIndexOrThrow(@Nullable String namespace, @NonNull String name) + throws XmlPullParserException { + final int index = getAttributeIndex(namespace, name); + if (index == -1) { + throw new XmlPullParserException("Missing attribute " + name); + } else { + return index; + } + } + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + @NonNull byte[] getAttributeBytesHex(int index) throws XmlPullParserException; + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + @NonNull byte[] getAttributeBytesBase64(int index) throws XmlPullParserException; + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + int getAttributeInt(int index) throws XmlPullParserException; + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + int getAttributeIntHex(int index) throws XmlPullParserException; + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + long getAttributeLong(int index) throws XmlPullParserException; + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + long getAttributeLongHex(int index) throws XmlPullParserException; + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + float getAttributeFloat(int index) throws XmlPullParserException; + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + double getAttributeDouble(int index) throws XmlPullParserException; + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + boolean getAttributeBoolean(int index) throws XmlPullParserException; + + /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - @NonNull byte[] getAttributeBytesHex(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default @NonNull byte[] getAttributeBytesHex(@Nullable String namespace, + @NonNull String name) throws XmlPullParserException { + return getAttributeBytesHex(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - @NonNull byte[] getAttributeBytesBase64(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default @NonNull byte[] getAttributeBytesBase64(@Nullable String namespace, + @NonNull String name) throws XmlPullParserException { + return getAttributeBytesBase64(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - int getAttributeInt(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default int getAttributeInt(@Nullable String namespace, @NonNull String name) + throws XmlPullParserException { + return getAttributeInt(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - int getAttributeIntHex(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default int getAttributeIntHex(@Nullable String namespace, @NonNull String name) + throws XmlPullParserException { + return getAttributeIntHex(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - long getAttributeLong(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default long getAttributeLong(@Nullable String namespace, @NonNull String name) + throws XmlPullParserException { + return getAttributeLong(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - long getAttributeLongHex(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default long getAttributeLongHex(@Nullable String namespace, @NonNull String name) + throws XmlPullParserException { + return getAttributeLongHex(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - float getAttributeFloat(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default float getAttributeFloat(@Nullable String namespace, @NonNull String name) + throws XmlPullParserException { + return getAttributeFloat(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - double getAttributeDouble(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default double getAttributeDouble(@Nullable String namespace, @NonNull String name) + throws XmlPullParserException { + return getAttributeDouble(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - boolean getAttributeBoolean(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default boolean getAttributeBoolean(@Nullable String namespace, @NonNull String name) + throws XmlPullParserException { + return getAttributeBoolean(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue}, otherwise @@ -98,8 +199,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default @Nullable byte[] getAttributeBytesHex(@Nullable String namespace, @NonNull String name, @Nullable byte[] defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeBytesHex(namespace, name); + return getAttributeBytesHex(index); } catch (Exception ignored) { return defaultValue; } @@ -111,8 +214,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default @Nullable byte[] getAttributeBytesBase64(@Nullable String namespace, @NonNull String name, @Nullable byte[] defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeBytesBase64(namespace, name); + return getAttributeBytesBase64(index); } catch (Exception ignored) { return defaultValue; } @@ -124,8 +229,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default int getAttributeInt(@Nullable String namespace, @NonNull String name, int defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeInt(namespace, name); + return getAttributeInt(index); } catch (Exception ignored) { return defaultValue; } @@ -137,8 +244,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default int getAttributeIntHex(@Nullable String namespace, @NonNull String name, int defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeIntHex(namespace, name); + return getAttributeIntHex(index); } catch (Exception ignored) { return defaultValue; } @@ -150,8 +259,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default long getAttributeLong(@Nullable String namespace, @NonNull String name, long defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeLong(namespace, name); + return getAttributeLong(index); } catch (Exception ignored) { return defaultValue; } @@ -163,8 +274,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default long getAttributeLongHex(@Nullable String namespace, @NonNull String name, long defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeLongHex(namespace, name); + return getAttributeLongHex(index); } catch (Exception ignored) { return defaultValue; } @@ -176,8 +289,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default float getAttributeFloat(@Nullable String namespace, @NonNull String name, float defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeFloat(namespace, name); + return getAttributeFloat(index); } catch (Exception ignored) { return defaultValue; } @@ -189,8 +304,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default double getAttributeDouble(@Nullable String namespace, @NonNull String name, double defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeDouble(namespace, name); + return getAttributeDouble(index); } catch (Exception ignored) { return defaultValue; } @@ -202,8 +319,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default boolean getAttributeBoolean(@Nullable String namespace, @NonNull String name, boolean defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeBoolean(namespace, name); + return getAttributeBoolean(index); } catch (Exception ignored) { return defaultValue; } diff --git a/core/java/android/util/proto/OWNERS b/core/java/android/util/proto/OWNERS new file mode 100644 index 000000000000..1eb6abf3233b --- /dev/null +++ b/core/java/android/util/proto/OWNERS @@ -0,0 +1,2 @@ +dplotnikov@google.com +mwachens@google.com diff --git a/core/java/android/view/IPinnedStackListener.aidl b/core/java/android/view/IPinnedStackListener.aidl index 84dd8af5e342..29c9c155e978 100644 --- a/core/java/android/view/IPinnedStackListener.aidl +++ b/core/java/android/view/IPinnedStackListener.aidl @@ -58,19 +58,6 @@ oneway interface IPinnedStackListener { void onActivityHidden(in ComponentName componentName); /** - * Called when the window manager has detected change on DisplayInfo, or - * when the listener is first registered to allow the listener to synchronized its state with - * the controller. - */ - void onDisplayInfoChanged(in DisplayInfo displayInfo); - - /** - * Called by the window manager at the beginning of a configuration update cascade - * since the metrics from these resources are used for bounds calculations. - */ - void onConfigurationChanged(); - - /** * Called by the window manager when the aspect ratio is reset. */ void onAspectRatioChanged(float aspectRatio); diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index 8da833a28efa..df96dc332ff0 100644 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -17,6 +17,7 @@ package android.view; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; @@ -28,7 +29,9 @@ import android.os.NullVibrator; import android.os.Parcel; import android.os.Parcelable; import android.os.Vibrator; +import android.os.VibratorManager; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; @@ -72,6 +75,9 @@ public final class InputDevice implements Parcelable { private Vibrator mVibrator; // guarded by mMotionRanges during initialization + @GuardedBy("mMotionRanges") + private VibratorManager mVibratorManager; + /** * A mask for input source classes. * @@ -415,6 +421,8 @@ public final class InputDevice implements Parcelable { private static final int MAX_RANGES = 1000; + private static final int VIBRATOR_ID_ALL = -1; + public static final @android.annotation.NonNull Parcelable.Creator<InputDevice> CREATOR = new Parcelable.Creator<InputDevice>() { public InputDevice createFromParcel(Parcel in) { @@ -785,7 +793,8 @@ public final class InputDevice implements Parcelable { synchronized (mMotionRanges) { if (mVibrator == null) { if (mHasVibrator) { - mVibrator = InputManager.getInstance().getInputDeviceVibrator(mId); + mVibrator = InputManager.getInstance().getInputDeviceVibrator(mId, + VIBRATOR_ID_ALL); } else { mVibrator = NullVibrator.getInstance(); } @@ -795,6 +804,24 @@ public final class InputDevice implements Parcelable { } /** + * Gets the vibrator manager associated with the device. + * Even if the device does not have a vibrator manager, the result is never null. + * Use {@link VibratorManager#getVibratorIds} to determine whether any vibrator is + * present. + * + * @return The vibrator manager associated with the device, never null. + */ + @NonNull + public VibratorManager getVibratorManager() { + synchronized (mMotionRanges) { + if (mVibratorManager == null) { + mVibratorManager = InputManager.getInstance().getInputDeviceVibratorManager(mId); + } + } + return mVibratorManager; + } + + /** * Returns true if input device is enabled. * @return Whether the input device is enabled. */ diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index a8d261553a8f..52b7cffbc340 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -477,6 +477,14 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int FLAG_IS_GENERATED_GESTURE = 0x8; /** + * This flag associated with {@link #ACTION_POINTER_UP}, this indicates that the pointer + * has been canceled. Typically this is used for palm event when the user has accidental + * touches. + * @hide + */ + public static final int FLAG_CANCELED = 0x20; + + /** * Private flag that indicates when the system has detected that this motion event * may be inconsistent with respect to the sequence of previously delivered motion events, * such as when a pointer move event is sent but the pointer is not down. @@ -3477,7 +3485,8 @@ public final class MotionEvent extends InputEvent implements Parcelable { } else if (newPointerCount == 1) { // The first/last pointer went down/up. newAction = oldActionMasked == ACTION_POINTER_DOWN - ? ACTION_DOWN : ACTION_UP; + ? ACTION_DOWN + : (getFlags() & FLAG_CANCELED) == 0 ? ACTION_UP : ACTION_CANCEL; } else { // A secondary pointer went down/up. newAction = oldActionMasked diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS index 7b60f2e1a6bd..4f82b86f260c 100644 --- a/core/java/android/view/OWNERS +++ b/core/java/android/view/OWNERS @@ -1,3 +1,14 @@ +# Bug component: 25700 + +romainguy@google.com +alanv@google.com +adamp@google.com +aurimas@google.com +nduca@google.com +sumir@google.com +ogunwale@google.com +jjaggi@google.com + # Display per-file Display.java = michaelwr@google.com, santoscordon@google.com per-file DisplayInfo.java = michaelwr@google.com, santoscordon@google.com diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index d7ee6ad15166..81e0852fdfa2 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -26,6 +26,7 @@ import static android.view.SurfaceControlProto.HASH_CODE; import static android.view.SurfaceControlProto.NAME; import android.annotation.FloatRange; +import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; @@ -54,12 +55,15 @@ import android.util.proto.ProtoOutputStream; import android.view.Surface.OutOfResourcesException; import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.VirtualRefBasePtr; import dalvik.system.CloseGuard; import libcore.util.NativeAllocationRegistry; import java.io.Closeable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -224,6 +228,10 @@ public final class SurfaceControl implements Parcelable { IBinder focusedToken, int displayId); private static native void nativeSetFrameTimelineVsync(long transactionObj, long frameTimelineVsyncId); + private static native void nativeAddJankDataListener(long nativeListener, + long nativeSurfaceControl); + private static native void nativeRemoveJankDataListener(long nativeListener); + private static native long nativeCreateJankDataListenerWrapper(OnJankDataListener listener); @Nullable @GuardedBy("mLock") @@ -249,6 +257,73 @@ public final class SurfaceControl implements Parcelable { void onReparent(@NonNull Transaction transaction, @Nullable SurfaceControl parent); } + /** + * Jank information to be fed back via {@link OnJankDataListener}. + * @hide + */ + public static class JankData { + + /** @hide */ + @IntDef(flag = true, value = {JANK_NONE, + JANK_DISPLAY, + JANK_SURFACEFLINGER_DEADLINE_MISSED, + JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED, + JANK_APP_DEADLINE_MISSED, + JANK_PREDICTION_EXPIRED, + JANK_SURFACEFLINGER_EARLY_LATCH}) + @Retention(RetentionPolicy.SOURCE) + public @interface JankType {} + + // Needs to be kept in sync with frameworks/native/libs/gui/include/gui/JankInfo.h + + // No Jank + public static final int JANK_NONE = 0x0; + + // Jank not related to SurfaceFlinger or the App + public static final int JANK_DISPLAY = 0x1; + // SF took too long on the CPU + public static final int JANK_SURFACEFLINGER_DEADLINE_MISSED = 0x2; + // SF took too long on the GPU + public static final int JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED = 0x4; + // Either App or GPU took too long on the frame + public static final int JANK_APP_DEADLINE_MISSED = 0x8; + // Predictions live for 120ms, if prediction is expired for a frame, there is definitely a + // jank + // associated with the App if this is for a SurfaceFrame, and SF for a DisplayFrame. + public static final int JANK_PREDICTION_EXPIRED = 0x10; + // Latching a buffer early might cause an early present of the frame + public static final int JANK_SURFACEFLINGER_EARLY_LATCH = 0x20; + + public JankData(long frameVsyncId, @JankType int jankType) { + this.frameVsyncId = frameVsyncId; + this.jankType = jankType; + } + + public final long frameVsyncId; + public final @JankType int jankType; + } + + /** + * Listener interface to be informed about SurfaceFlinger's jank classification for a specific + * surface. + * + * @see JankData + * @see #addJankDataListener + * @hide + */ + public static abstract class OnJankDataListener { + private final VirtualRefBasePtr mNativePtr; + + public OnJankDataListener() { + mNativePtr = new VirtualRefBasePtr(nativeCreateJankDataListenerWrapper(this)); + } + + /** + * Called when new jank classifications are available. + */ + public abstract void onJankDataAvailable(JankData[] jankStats); + } + private final CloseGuard mCloseGuard = CloseGuard.get(); private String mName; @@ -2519,6 +2594,22 @@ public final class SurfaceControl implements Parcelable { nativeSetGlobalShadowSettings(ambientColor, spotColor, lightPosY, lightPosZ, lightRadius); } + /** + * Adds a callback to be informed about SF's jank classification for a specific surface. + * @hide + */ + public static void addJankDataListener(OnJankDataListener listener, SurfaceControl surface) { + nativeAddJankDataListener(listener.mNativePtr.get(), surface.mNativeObject); + } + + /** + * Removes a jank callback previously added with {@link #addJankDataListener} + * @hide + */ + public static void removeJankDataListener(OnJankDataListener listener) { + nativeRemoveJankDataListener(listener.mNativePtr.get()); + } + /** * An atomic set of changes to a set of SurfaceControl. */ diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 29cc4b507acc..9943e0203298 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -29023,6 +29023,33 @@ public class View implements Drawable.Callback, KeyEvent.Callback, boolean mUse32BitDrawingCache; /** + * For windows that are full-screen but using insets to layout inside + * of the screen decorations, these are the current insets for the + * content of the window. + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, + publicAlternatives = "Use {@link WindowInsets#getInsets(int)}") + final Rect mContentInsets = new Rect(); + + /** + * For windows that are full-screen but using insets to layout inside + * of the screen decorations, these are the current insets for the + * actual visible parts of the window. + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, + publicAlternatives = "Use {@link WindowInsets#getInsets(int)}") + final Rect mVisibleInsets = new Rect(); + + /** + * For windows that are full-screen but using insets to layout inside + * of the screen decorations, these are the current insets for the + * stable system windows. + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, + publicAlternatives = "Use {@link WindowInsets#getInsets(int)}") + final Rect mStableInsets = new Rect(); + + /** * Current caption insets to the display coordinate. */ final Rect mCaptionInsets = new Rect(); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 2d633cbeb353..863ee7bb17da 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -582,9 +582,6 @@ public final class ViewRootImpl implements ViewParent, = new ViewTreeObserver.InternalInsetsInfo(); private WindowInsets mLastWindowInsets; - private final Rect mSystemInsetsCache = new Rect(); - private final Rect mVisibleInsetsCache = new Rect(); - private final Rect mStableInsetsCache = new Rect(); // Insets types hidden by legacy window flags or system UI flags. private @InsetsType int mTypesHiddenByFlags = 0; @@ -2341,9 +2338,9 @@ public final class ViewRootImpl implements ViewParent, (mWindowAttributes.systemUiVisibility | mWindowAttributes.subtreeSystemUiVisibility)); - mSystemInsetsCache.set(mLastWindowInsets.getSystemWindowInsets().toRect()); - mStableInsetsCache.set(mLastWindowInsets.getStableInsets().toRect()); - mVisibleInsetsCache.set(mInsetsController.calculateVisibleInsets( + mAttachInfo.mContentInsets.set(mLastWindowInsets.getSystemWindowInsets().toRect()); + mAttachInfo.mStableInsets.set(mLastWindowInsets.getStableInsets().toRect()); + mAttachInfo.mVisibleInsets.set(mInsetsController.calculateVisibleInsets( mWindowAttributes.softInputMode)); } return mLastWindowInsets; @@ -2846,7 +2843,7 @@ public final class ViewRootImpl implements ViewParent, && mWinFrame.height() == mPendingBackDropFrame.height(); // TODO: Need cutout? startDragResizing(mPendingBackDropFrame, !backdropSizeMatchesFrame, - mSystemInsetsCache, mStableInsetsCache, mResizeMode); + mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mResizeMode); } else { // We shouldn't come here, but if we come we should end the resize. endDragResizing(); @@ -4478,8 +4475,8 @@ public final class ViewRootImpl implements ViewParent, } boolean scrollToRectOrFocus(Rect rectangle, boolean immediate) { - final Rect ci = mSystemInsetsCache; - final Rect vi = mVisibleInsetsCache; + final Rect ci = mAttachInfo.mContentInsets; + final Rect vi = mAttachInfo.mVisibleInsets; int scrollY = 0; boolean handled = false; @@ -7575,7 +7572,7 @@ public final class ViewRootImpl implements ViewParent, // XXX This is really broken, and probably all needs to be done // in the window manager, and we need to know more about whether // we want the area behind or in front of the IME. - final Rect insets = mVisibleInsetsCache; + final Rect insets = mAttachInfo.mVisibleInsets; outFrame.left += insets.left; outFrame.top += insets.top; outFrame.right -= insets.right; @@ -7913,7 +7910,7 @@ public final class ViewRootImpl implements ViewParent, synchronized (mWindowCallbacks) { for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { mWindowCallbacks.get(i).onWindowSizeIsChanging(backDropFrame, fullscreen, - mVisibleInsetsCache, mStableInsetsCache); + mAttachInfo.mVisibleInsets, mAttachInfo.mStableInsets); } } } diff --git a/core/java/android/view/accessibility/OWNERS b/core/java/android/view/accessibility/OWNERS index c6f42f719caa..93b5a2e8bc28 100644 --- a/core/java/android/view/accessibility/OWNERS +++ b/core/java/android/view/accessibility/OWNERS @@ -1,4 +1,11 @@ -svetoslavganov@google.com +# Bug component: 44214 + +romainguy@google.com +alanv@google.com +adamp@google.com +aurimas@google.com +nduca@google.com +sumir@google.com +ogunwale@google.com +jjaggi@google.com pweaver@google.com -rhedjao@google.com -qasid@google.com diff --git a/core/java/android/view/animation/OWNERS b/core/java/android/view/animation/OWNERS new file mode 100644 index 000000000000..9b8f4d995975 --- /dev/null +++ b/core/java/android/view/animation/OWNERS @@ -0,0 +1,6 @@ +# Bug component: 25700 + +romainguy@google.com +tianliu@google.com +alanv@google.com +adamp@google.com diff --git a/core/java/android/view/autofill/OWNERS b/core/java/android/view/autofill/OWNERS new file mode 100644 index 000000000000..a08863276da7 --- /dev/null +++ b/core/java/android/view/autofill/OWNERS @@ -0,0 +1,9 @@ +# Bug component: 351486 + +joannechung@google.com +adamhe@google.com +tymtsai@google.com +lpeter@google.com +augale@google.com +svetoslavganov@android.com +svetoslavganov@google.com diff --git a/core/java/android/view/contentcapture/OWNERS b/core/java/android/view/contentcapture/OWNERS new file mode 100644 index 000000000000..6337327cec25 --- /dev/null +++ b/core/java/android/view/contentcapture/OWNERS @@ -0,0 +1,9 @@ +# Bug component: 544200 + +joannechung@google.com +adamhe@google.com +tymtsai@google.com +lpeter@google.com +augale@google.com +svetoslavganov@android.com +svetoslavganov@google.com diff --git a/core/java/android/view/inputmethod/OWNERS b/core/java/android/view/inputmethod/OWNERS index 244cc30e089e..e6a04dad25c2 100644 --- a/core/java/android/view/inputmethod/OWNERS +++ b/core/java/android/view/inputmethod/OWNERS @@ -1,3 +1,4 @@ +# Bug component: 34867 set noparent -include ../../../../../services/core/java/com/android/server/inputmethod/OWNERS +include /services/core/java/com/android/server/inputmethod/OWNERS diff --git a/core/java/android/view/inspector/OWNERS b/core/java/android/view/inspector/OWNERS index c2827cc31592..705f4b342d42 100644 --- a/core/java/android/view/inspector/OWNERS +++ b/core/java/android/view/inspector/OWNERS @@ -1,3 +1,6 @@ +romainguy@google.com alanv@google.com +adamp@google.com aurimas@google.com -emberrose@google.com +nduca@google.com +sumir@google.com diff --git a/core/java/android/view/textclassifier/OWNERS b/core/java/android/view/textclassifier/OWNERS index be4fbaa6d06a..ac80d9f4cdd0 100644 --- a/core/java/android/view/textclassifier/OWNERS +++ b/core/java/android/view/textclassifier/OWNERS @@ -1,14 +1,8 @@ # Bug component: 709498 +mns@google.com toki@google.com -tonymak@google.com -zilka@google.com -jalt@google.com -joannechung@google.com +svetoslavganov@android.com svetoslavganov@google.com -eugeniom@google.com -samsellem@google.com -adamhe@google.com augale@google.com -lpeter@google.com -tymtsai@google.com
\ No newline at end of file +joannechung@google.com diff --git a/core/java/android/view/textclassifier/intent/OWNERS b/core/java/android/view/textclassifier/intent/OWNERS new file mode 100644 index 000000000000..ac80d9f4cdd0 --- /dev/null +++ b/core/java/android/view/textclassifier/intent/OWNERS @@ -0,0 +1,8 @@ +# Bug component: 709498 + +mns@google.com +toki@google.com +svetoslavganov@android.com +svetoslavganov@google.com +augale@google.com +joannechung@google.com diff --git a/core/java/android/view/textclassifier/logging/OWNERS b/core/java/android/view/textclassifier/logging/OWNERS new file mode 100644 index 000000000000..ac80d9f4cdd0 --- /dev/null +++ b/core/java/android/view/textclassifier/logging/OWNERS @@ -0,0 +1,8 @@ +# Bug component: 709498 + +mns@google.com +toki@google.com +svetoslavganov@android.com +svetoslavganov@google.com +augale@google.com +joannechung@google.com diff --git a/core/java/android/view/textservice/OWNERS b/core/java/android/view/textservice/OWNERS new file mode 100644 index 000000000000..a637754ba17a --- /dev/null +++ b/core/java/android/view/textservice/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 34867 + +ogunwale@google.com +roosa@google.com +yukawa@google.com diff --git a/core/java/android/widget/OWNERS b/core/java/android/widget/OWNERS index 5c79d21791e3..fbb975b806f1 100644 --- a/core/java/android/widget/OWNERS +++ b/core/java/android/widget/OWNERS @@ -1 +1,9 @@ +# Bug component: 25700 + +romainguy@google.com +alanv@google.com +adamp@google.com +aurimas@google.com +siyamed@google.com + per-file TextView.java, EditText.java, Editor.java = siyamed@google.com, nona@google.com, clarabayarri@google.com diff --git a/core/java/android/window/OWNERS b/core/java/android/window/OWNERS index d10fb31e104f..2c61df96eb03 100644 --- a/core/java/android/window/OWNERS +++ b/core/java/android/window/OWNERS @@ -1,3 +1,3 @@ set noparent -include ../../../../services/core/java/com/android/server/wm/OWNERS +include /services/core/java/com/android/server/wm/OWNERS diff --git a/core/java/com/android/ims/OWNERS b/core/java/com/android/ims/OWNERS new file mode 100644 index 000000000000..640baf2297b4 --- /dev/null +++ b/core/java/com/android/ims/OWNERS @@ -0,0 +1 @@ +include /telephony/OWNERS diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java index 3e1fa1d5fe59..0f37dc5949f9 100644 --- a/core/java/com/android/internal/app/IntentForwarderActivity.java +++ b/core/java/com/android/internal/app/IntentForwarderActivity.java @@ -24,7 +24,6 @@ import static com.android.internal.app.ResolverActivity.EXTRA_SELECTED_PROFILE; import android.annotation.Nullable; import android.annotation.StringRes; import android.app.Activity; -import android.app.ActivityTaskManager; import android.app.ActivityThread; import android.app.AppGlobals; import android.app.admin.DevicePolicyManager; @@ -199,18 +198,8 @@ public class IntentForwarderActivity extends Activity { /* ignoreTargetSecurity= */ false, userId); } catch (RuntimeException e) { - int launchedFromUid = -1; - String launchedFromPackage = "?"; - try { - launchedFromUid = ActivityTaskManager.getService().getLaunchedFromUid( - getActivityToken()); - launchedFromPackage = ActivityTaskManager.getService() - .getLaunchedFromPackage(getActivityToken()); - } catch (RemoteException ignored) { - } - - Slog.wtf(TAG, "Unable to launch as UID " + launchedFromUid + " package " - + launchedFromPackage + ", while running in " + Slog.wtf(TAG, "Unable to launch as UID " + getLaunchedFromUid() + " package " + + getLaunchedFromPackage() + ", while running in " + ActivityThread.currentProcessName(), e); } } diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 83cbe38f6cb4..6f9da6fa94a3 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -350,13 +350,7 @@ public class ResolverActivity extends Activity implements // from managed profile to owner or other way around. setProfileSwitchMessageId(intent.getContentUserHint()); - try { - mLaunchedFromUid = ActivityTaskManager.getService().getLaunchedFromUid( - getActivityToken()); - } catch (RemoteException e) { - mLaunchedFromUid = -1; - } - + mLaunchedFromUid = getLaunchedFromUid(); if (mLaunchedFromUid < 0 || UserHandle.isIsolated(mLaunchedFromUid)) { // Gulp! finish(); @@ -1085,7 +1079,7 @@ public class ResolverActivity extends Activity implements } } - protected boolean onTargetSelected(TargetInfo target, boolean alwaysCheck) { + protected boolean onTargetSelected(TargetInfo target, boolean always) { final ResolveInfo ri = target.getResolveInfo(); final Intent intent = target != null ? target.getResolvedIntent() : null; @@ -1207,7 +1201,7 @@ public class ResolverActivity extends Activity implements if (otherProfileMatch > bestMatch) bestMatch = otherProfileMatch; } - if (alwaysCheck) { + if (always) { final int userId = getUserId(); final PackageManager pm = getPackageManager(); @@ -1220,25 +1214,6 @@ public class ResolverActivity extends Activity implements if (TextUtils.isEmpty(packageName)) { pm.setDefaultBrowserPackageNameAsUser(ri.activityInfo.packageName, userId); } - } else { - // Update Domain Verification status - ComponentName cn = intent.getComponent(); - String packageName = cn.getPackageName(); - String dataScheme = (data != null) ? data.getScheme() : null; - - boolean isHttpOrHttps = (dataScheme != null) && - (dataScheme.equals(IntentFilter.SCHEME_HTTP) || - dataScheme.equals(IntentFilter.SCHEME_HTTPS)); - - boolean isViewAction = (action != null) && action.equals(Intent.ACTION_VIEW); - boolean hasCategoryBrowsable = (categories != null) && - categories.contains(Intent.CATEGORY_BROWSABLE); - - if (isHttpOrHttps && isViewAction && hasCategoryBrowsable) { - pm.updateIntentVerificationStatusAsUser(packageName, - PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS, - userId); - } } } else { try { @@ -1319,15 +1294,8 @@ public class ResolverActivity extends Activity implements maybeLogCrossProfileTargetLaunch(cti, currentUserHandle); } } catch (RuntimeException e) { - String launchedFromPackage; - try { - launchedFromPackage = ActivityTaskManager.getService().getLaunchedFromPackage( - getActivityToken()); - } catch (RemoteException e2) { - launchedFromPackage = "??"; - } Slog.wtf(TAG, "Unable to launch as uid " + mLaunchedFromUid - + " package " + launchedFromPackage + ", while running in " + + " package " + getLaunchedFromPackage() + ", while running in " + ActivityThread.currentProcessName(), e); } } diff --git a/core/java/com/android/internal/config/sysui/OWNERS b/core/java/com/android/internal/config/sysui/OWNERS new file mode 100644 index 000000000000..2e96c97c8bb3 --- /dev/null +++ b/core/java/com/android/internal/config/sysui/OWNERS @@ -0,0 +1 @@ +include /packages/SystemUI/OWNERS diff --git a/core/java/com/android/internal/jank/OWNERS b/core/java/com/android/internal/jank/OWNERS new file mode 100644 index 000000000000..352c132fda4f --- /dev/null +++ b/core/java/com/android/internal/jank/OWNERS @@ -0,0 +1,6 @@ +include /services/core/java/com/android/server/wm/OWNERS + +# Jank people +ahanwu@google.com +vadimt@google.com +marcinoc@google.com
\ No newline at end of file diff --git a/core/java/com/android/internal/net/OWNERS b/core/java/com/android/internal/net/OWNERS index 050cb5c2b44e..fec56c3cc506 100644 --- a/core/java/com/android/internal/net/OWNERS +++ b/core/java/com/android/internal/net/OWNERS @@ -3,7 +3,7 @@ set noparent codewiz@google.com ek@google.com jchalard@google.com -jsharkey@android.com +jsharkey@google.com lorenzo@google.com reminv@google.com satk@google.com diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index fb6eb97253e3..4476e7e8e99d 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -106,7 +106,6 @@ import com.android.internal.power.MeasuredEnergyArray; import com.android.internal.power.MeasuredEnergyStats; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastPrintWriter; -import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.XmlUtils; @@ -122,7 +121,6 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -1080,16 +1078,6 @@ public class BatteryStatsImpl extends BatteryStats { private long[] mCpuFreqs; /** - * Times spent by the system server process grouped by cluster and CPU speed. - */ - private LongSamplingCounterArray mSystemServerCpuTimesUs; - - /** - * Times spent by the system server threads grouped by cluster and CPU speed. - */ - private LongSamplingCounterArray mSystemServerThreadCpuTimesUs; - - /** * Times spent by the system server threads handling incoming binder requests. */ private LongSamplingCounterArray mBinderThreadCpuTimesUs; @@ -10756,6 +10744,14 @@ public class BatteryStatsImpl extends BatteryStats { } } + /** + * Starts tracking CPU time-in-state for threads of the system server process, + * keeping a separate account of threads receiving incoming binder calls. + */ + public void startTrackingSystemServerCpuTime() { + mSystemServerCpuThreadReader.startTrackingThreadCpuTime(); + } + public void setCallback(BatteryCallback cb) { mCallback = cb; } @@ -11411,8 +11407,6 @@ public class BatteryStatsImpl extends BatteryStats { mExternalSync.scheduleSync("reset", ExternalStatsSync.UPDATE_ENERGY); } - resetIfNotNull(mSystemServerCpuTimesUs, false, elapsedRealtimeUs); - resetIfNotNull(mSystemServerThreadCpuTimesUs, false, elapsedRealtimeUs); resetIfNotNull(mBinderThreadCpuTimesUs, false, elapsedRealtimeUs); mLastHistoryStepDetails = null; @@ -12511,27 +12505,17 @@ public class BatteryStatsImpl extends BatteryStats { return; } - if (mSystemServerCpuTimesUs == null) { - mSystemServerCpuTimesUs = new LongSamplingCounterArray(mOnBatteryTimeBase); - mSystemServerThreadCpuTimesUs = new LongSamplingCounterArray(mOnBatteryTimeBase); + if (mBinderThreadCpuTimesUs == null) { mBinderThreadCpuTimesUs = new LongSamplingCounterArray(mOnBatteryTimeBase); } - mSystemServerCpuTimesUs.addCountLocked(systemServiceCpuThreadTimes.processCpuTimesUs); - mSystemServerThreadCpuTimesUs.addCountLocked(systemServiceCpuThreadTimes.threadCpuTimesUs); mBinderThreadCpuTimesUs.addCountLocked(systemServiceCpuThreadTimes.binderThreadCpuTimesUs); if (DEBUG_BINDER_STATS) { - Slog.d(TAG, "System server threads per CPU cluster (binder threads/total threads/%)"); - long totalCpuTimeMs = 0; - long totalThreadTimeMs = 0; + Slog.d(TAG, "System server threads per CPU cluster (incoming binder threads)"); long binderThreadTimeMs = 0; int cpuIndex = 0; - final long[] systemServerCpuTimesUs = - mSystemServerCpuTimesUs.getCountsLocked(0); - final long[] systemServerThreadCpuTimesUs = - mSystemServerThreadCpuTimesUs.getCountsLocked(0); - final long[] binderThreadCpuTimesUs = - mBinderThreadCpuTimesUs.getCountsLocked(0); + final long[] binderThreadCpuTimesUs = mBinderThreadCpuTimesUs.getCountsLocked( + BatteryStats.STATS_SINCE_CHARGED); int index = 0; int numCpuClusters = mPowerProfile.getNumCpuClusters(); for (int cluster = 0; cluster < numCpuClusters; cluster++) { @@ -12542,28 +12526,15 @@ public class BatteryStatsImpl extends BatteryStats { if (speed != 0) { sb.append(", "); } - long totalCountMs = systemServerThreadCpuTimesUs[index] / 1000; long binderCountMs = binderThreadCpuTimesUs[index] / 1000; - sb.append(String.format("%d/%d(%.1f%%)", - binderCountMs, - totalCountMs, - totalCountMs != 0 ? (double) binderCountMs * 100 / totalCountMs : 0)); + sb.append(TextUtils.formatSimple("%10d", binderCountMs)); - totalCpuTimeMs += systemServerCpuTimesUs[index] / 1000; - totalThreadTimeMs += totalCountMs; binderThreadTimeMs += binderCountMs; index++; } cpuIndex += mPowerProfile.getNumCoresInCpuCluster(cluster); Slog.d(TAG, sb.toString()); } - - Slog.d(TAG, "Total system server CPU time (ms): " + totalCpuTimeMs); - Slog.d(TAG, "Total system server thread time (ms): " + totalThreadTimeMs); - Slog.d(TAG, String.format("Total Binder thread time (ms): %d (%.1f%%)", - binderThreadTimeMs, - binderThreadTimeMs != 0 - ? (double) binderThreadTimeMs * 100 / totalThreadTimeMs : 0)); } } @@ -13853,60 +13824,16 @@ public class BatteryStatsImpl extends BatteryStats { } + /** + * Estimates the time spent by the system server handling incoming binder requests. + */ @Override public long[] getSystemServiceTimeAtCpuSpeeds() { - // Estimates the time spent by the system server handling incoming binder requests. - // - // The data that we can get from the kernel is this: - // - CPU duration for a (thread - cluster - CPU speed) combination - // - CPU duration for a (UID - cluster - CPU speed) combination - // - // The configuration we have in the Power Profile is this: - // - Average CPU power for a (cluster - CPU speed) combination. - // - // The model used by BatteryStats can be illustrated with this example: - // - // - Let's say the system server has 10 threads. - // - These 10 threads spent 1000 ms of CPU time in aggregate - // - Of the 10 threads 4 were execute exclusively incoming binder calls. - // - These 4 "binder" threads consumed 600 ms of CPU time in aggregate - // - The real time spent by the system server process doing all of this is, say, 200 ms. - // - // We will assume that power consumption is proportional to the time spent by the CPU - // across all threads. This is a crude assumption, but we don't have more detailed data. - // Thus, - // binderRealTime = realTime * aggregateBinderThreadTime / aggregateAllThreadTime - // - // In our example, - // binderRealTime = 200 * 600 / 1000 = 120ms - // - // We can then multiply this estimated time by the average power to obtain an estimate - // of the total power consumed by incoming binder calls for the given cluster/speed - // combination. - - if (mSystemServerCpuTimesUs == null) { + if (mBinderThreadCpuTimesUs == null) { return null; } - final long[] systemServerCpuTimesUs = mSystemServerCpuTimesUs.getCountsLocked( - BatteryStats.STATS_SINCE_CHARGED); - final long [] systemServerThreadCpuTimesUs = mSystemServerThreadCpuTimesUs.getCountsLocked( - BatteryStats.STATS_SINCE_CHARGED); - final long[] binderThreadCpuTimesUs = mBinderThreadCpuTimesUs.getCountsLocked( - BatteryStats.STATS_SINCE_CHARGED); - - final int size = systemServerCpuTimesUs.length; - final long[] results = new long[size]; - - for (int i = 0; i < size; i++) { - if (systemServerThreadCpuTimesUs[i] == 0) { - continue; - } - - results[i] = systemServerCpuTimesUs[i] * binderThreadCpuTimesUs[i] - / systemServerThreadCpuTimesUs[i]; - } - return results; + return mBinderThreadCpuTimesUs.getCountsLocked(BatteryStats.STATS_SINCE_CHARGED); } /** @@ -13935,10 +13862,6 @@ public class BatteryStatsImpl extends BatteryStats { return u; } - public void onCleanupUserLocked(int userId) { - onCleanupUserLocked(userId, mClocks.elapsedRealtime()); - } - public void onCleanupUserLocked(int userId, long elapsedRealtimeMs) { final int firstUidForUser = UserHandle.getUid(userId, 0); final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1); @@ -14306,7 +14229,7 @@ public class BatteryStatsImpl extends BatteryStats { } updateSystemServiceCallStats(); - if (mSystemServerThreadCpuTimesUs != null) { + if (mBinderThreadCpuTimesUs != null) { pw.println("Per UID System server binder time in ms:"); long[] systemServiceTimeAtCpuSpeeds = getSystemServiceTimeAtCpuSpeeds(); for (int i = 0; i < size; i++) { @@ -15872,9 +15795,6 @@ public class BatteryStatsImpl extends BatteryStats { mUidStats.append(uid, u); } - mSystemServerCpuTimesUs = LongSamplingCounterArray.readFromParcel(in, mOnBatteryTimeBase); - mSystemServerThreadCpuTimesUs = LongSamplingCounterArray.readFromParcel(in, - mOnBatteryTimeBase); mBinderThreadCpuTimesUs = LongSamplingCounterArray.readFromParcel(in, mOnBatteryTimeBase); } @@ -16083,8 +16003,6 @@ public class BatteryStatsImpl extends BatteryStats { } else { out.writeInt(0); } - LongSamplingCounterArray.writeToParcel(out, mSystemServerCpuTimesUs); - LongSamplingCounterArray.writeToParcel(out, mSystemServerThreadCpuTimesUs); LongSamplingCounterArray.writeToParcel(out, mBinderThreadCpuTimesUs); } diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java index 62e9f98181ab..e1d0a151c723 100644 --- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java +++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java @@ -17,13 +17,18 @@ package com.android.internal.os; import android.content.Context; -import android.os.BatteryConsumer; +import android.hardware.SensorManager; +import android.net.ConnectivityManager; import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.Bundle; +import android.os.SystemClock; import android.os.UidBatteryConsumer; +import android.os.UserHandle; import android.os.UserManager; +import android.util.SparseArray; +import java.util.ArrayList; import java.util.List; /** @@ -33,10 +38,53 @@ import java.util.List; public class BatteryUsageStatsProvider { private final Context mContext; private final BatteryStatsImpl mStats; + private final PowerProfile mPowerProfile; + private final Object mLock = new Object(); + private List<PowerCalculator> mPowerCalculators; public BatteryUsageStatsProvider(Context context, BatteryStatsImpl stats) { mContext = context; mStats = stats; + mPowerProfile = new PowerProfile(mContext); + } + + private List<PowerCalculator> getPowerCalculators() { + synchronized (mLock) { + if (mPowerCalculators == null) { + mPowerCalculators = new ArrayList<>(); + + // Power calculators are applied in the order of registration + mPowerCalculators.add(new CpuPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new MemoryPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new WakelockPowerCalculator(mPowerProfile)); + if (!isWifiOnlyDevice(mContext)) { + mPowerCalculators.add(new MobileRadioPowerCalculator(mPowerProfile)); + } + mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new BluetoothPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new SensorPowerCalculator(mPowerProfile, + mContext.getSystemService(SensorManager.class))); + mPowerCalculators.add(new CameraPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new FlashlightPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new MediaPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new PhonePowerCalculator(mPowerProfile)); + mPowerCalculators.add(new ScreenPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new AmbientDisplayPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new SystemServicePowerCalculator(mPowerProfile)); + mPowerCalculators.add(new IdlePowerCalculator(mPowerProfile)); + + mPowerCalculators.add(new UserPowerCalculator()); + } + } + return mPowerCalculators; + } + + private static boolean isWifiOnlyDevice(Context context) { + ConnectivityManager cm = context.getSystemService(ConnectivityManager.class); + if (cm == null) { + return false; + } + return !cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); } /** @@ -49,11 +97,19 @@ public class BatteryUsageStatsProvider { false /* collectBatteryBroadcast */); batteryStatsHelper.create((Bundle) null); final UserManager userManager = mContext.getSystemService(UserManager.class); - batteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, - userManager.getUserProfiles()); + final List<UserHandle> asUsers = userManager.getUserProfiles(); + final int n = asUsers.size(); + SparseArray<UserHandle> users = new SparseArray<>(n); + for (int i = 0; i < n; ++i) { + UserHandle userHandle = asUsers.get(i); + users.put(userHandle.getIdentifier(), userHandle); + } + + batteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, users); // TODO(b/174186358): read extra power component number from configuration final int customPowerComponentCount = 0; + final int customTimeComponentCount = 0; final BatteryUsageStats.Builder batteryUsageStatsBuilder = new BatteryUsageStats.Builder() .setDischargePercentage(batteryStatsHelper.getStats().getDischargeAmount(0)) .setConsumedPower(batteryStatsHelper.getTotalPower()); @@ -62,15 +118,23 @@ public class BatteryUsageStatsProvider { for (int i = 0; i < usageList.size(); i++) { final BatterySipper sipper = usageList.get(i); if (sipper.drainType == BatterySipper.DrainType.APP) { - batteryUsageStatsBuilder.addUidBatteryConsumer( - new UidBatteryConsumer.Builder(customPowerComponentCount, sipper.getUid()) + batteryUsageStatsBuilder.addUidBatteryConsumerBuilder( + new UidBatteryConsumer.Builder(customPowerComponentCount, + customTimeComponentCount, sipper.uidObj) .setPackageWithHighestDrain(sipper.packageWithHighestDrain) - .setConsumedPower(sipper.sumPower()) - .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, - sipper.cpuPowerMah) - .build()); + .setConsumedPower(sipper.sumPower())); } } + + final long realtimeUs = SystemClock.elapsedRealtime() * 1000; + final long uptimeUs = SystemClock.uptimeMillis() * 1000; + + final List<PowerCalculator> powerCalculators = getPowerCalculators(); + for (PowerCalculator powerCalculator : powerCalculators) { + powerCalculator.calculate(batteryUsageStatsBuilder, mStats, realtimeUs, uptimeUs, + BatteryStats.STATS_SINCE_CHARGED, users); + } + return batteryUsageStatsBuilder.build(); } } diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java index dac62a678665..732d2916a092 100644 --- a/core/java/com/android/internal/os/CpuPowerCalculator.java +++ b/core/java/com/android/internal/os/CpuPowerCalculator.java @@ -16,6 +16,7 @@ package com.android.internal.os; import android.os.BatteryStats; +import android.os.UidBatteryConsumer; import android.util.ArrayMap; import android.util.Log; @@ -30,9 +31,9 @@ public class CpuPowerCalculator extends PowerCalculator { } @Override - protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs, - long rawUptimeUs, int statsType) { - app.cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000; + protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u, + long rawRealtimeUs, long rawUptimeUs, int statsType) { + long cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000; final int numClusters = mProfile.getNumCpuClusters(); double cpuPowerMaUs = 0; @@ -70,47 +71,52 @@ public class CpuPowerCalculator extends PowerCalculator { + numClusters + " actual # " + cpuClusterTimes.length); } } - app.cpuPowerMah = cpuPowerMaUs / MICROSEC_IN_HR; + final double cpuPowerMah = cpuPowerMaUs / MICROSEC_IN_HR; - if (DEBUG && (app.cpuTimeMs != 0 || app.cpuPowerMah != 0)) { - Log.d(TAG, "UID " + u.getUid() + ": CPU time=" + app.cpuTimeMs + " ms power=" - + formatCharge(app.cpuPowerMah)); + if (DEBUG && (cpuTimeMs != 0 || cpuPowerMah != 0)) { + Log.d(TAG, "UID " + u.getUid() + ": CPU time=" + cpuTimeMs + " ms power=" + + formatCharge(cpuPowerMah)); } // Keep track of the package with highest drain. double highestDrain = 0; - - app.cpuFgTimeMs = 0; + String packageWithHighestDrain = null; + long cpuFgTimeMs = 0; final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats(); final int processStatsCount = processStats.size(); for (int i = 0; i < processStatsCount; i++) { final BatteryStats.Uid.Proc ps = processStats.valueAt(i); final String processName = processStats.keyAt(i); - app.cpuFgTimeMs += ps.getForegroundTime(statsType); + cpuFgTimeMs += ps.getForegroundTime(statsType); final long costValue = ps.getUserTime(statsType) + ps.getSystemTime(statsType) + ps.getForegroundTime(statsType); // Each App can have multiple packages and with multiple running processes. // Keep track of the package who's process has the highest drain. - if (app.packageWithHighestDrain == null || - app.packageWithHighestDrain.startsWith("*")) { + if (packageWithHighestDrain == null || packageWithHighestDrain.startsWith("*")) { highestDrain = costValue; - app.packageWithHighestDrain = processName; + packageWithHighestDrain = processName; } else if (highestDrain < costValue && !processName.startsWith("*")) { highestDrain = costValue; - app.packageWithHighestDrain = processName; + packageWithHighestDrain = processName; } } + // Ensure that the CPU times make sense. - if (app.cpuFgTimeMs > app.cpuTimeMs) { - if (DEBUG && app.cpuFgTimeMs > app.cpuTimeMs + 10000) { + if (cpuFgTimeMs > cpuTimeMs) { + if (DEBUG && cpuFgTimeMs > cpuTimeMs + 10000) { Log.d(TAG, "WARNING! Cputime is more than 10 seconds behind Foreground time"); } // Statistics may not have been gathered yet. - app.cpuTimeMs = app.cpuFgTimeMs; + cpuTimeMs = cpuFgTimeMs; } + + app.setConsumedPower(UidBatteryConsumer.POWER_COMPONENT_CPU, cpuPowerMah); + app.setUsageDurationMillis(UidBatteryConsumer.TIME_COMPONENT_CPU, cpuTimeMs); + app.setUsageDurationMillis(UidBatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND, cpuFgTimeMs); + app.setPackageWithHighestDrain(packageWithHighestDrain); } } diff --git a/core/java/com/android/internal/os/KernelSingleProcessCpuThreadReader.java b/core/java/com/android/internal/os/KernelSingleProcessCpuThreadReader.java index e6a962312a00..4d2a08a4bcf3 100644 --- a/core/java/com/android/internal/os/KernelSingleProcessCpuThreadReader.java +++ b/core/java/com/android/internal/os/KernelSingleProcessCpuThreadReader.java @@ -16,23 +16,12 @@ package com.android.internal.os; -import static android.os.Process.PROC_OUT_LONG; -import static android.os.Process.PROC_SPACE_TERM; - import android.annotation.Nullable; -import android.os.Process; -import android.system.Os; -import android.system.OsConstants; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import java.io.IOException; -import java.nio.file.DirectoryIteratorException; -import java.nio.file.DirectoryStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Arrays; /** @@ -45,93 +34,65 @@ public class KernelSingleProcessCpuThreadReader { private static final String TAG = "KernelSingleProcCpuThreadRdr"; private static final boolean DEBUG = false; - private static final boolean NATIVE_ENABLED = true; - - /** - * The name of the file to read CPU statistics from, must be found in {@code - * /proc/$PID/task/$TID} - */ - private static final String CPU_STATISTICS_FILENAME = "time_in_state"; - - private static final String PROC_STAT_FILENAME = "stat"; - - /** Directory under /proc/$PID containing CPU stats files for threads */ - public static final String THREAD_CPU_STATS_DIRECTORY = "task"; - - /** Default mount location of the {@code proc} filesystem */ - private static final Path DEFAULT_PROC_PATH = Paths.get("/proc"); - - /** The initial {@code time_in_state} file for {@link ProcTimeInStateReader} */ - private static final Path INITIAL_TIME_IN_STATE_PATH = Paths.get("self/time_in_state"); - - /** See https://man7.org/linux/man-pages/man5/proc.5.html */ - private static final int[] PROCESS_FULL_STATS_FORMAT = new int[] { - PROC_SPACE_TERM, - PROC_SPACE_TERM, - PROC_SPACE_TERM, - PROC_SPACE_TERM, - PROC_SPACE_TERM, - PROC_SPACE_TERM, - PROC_SPACE_TERM, - PROC_SPACE_TERM, - PROC_SPACE_TERM, - PROC_SPACE_TERM, - PROC_SPACE_TERM, - PROC_SPACE_TERM, - PROC_SPACE_TERM, - PROC_SPACE_TERM | PROC_OUT_LONG, // 14: utime - PROC_SPACE_TERM | PROC_OUT_LONG, // 15: stime - // Ignore remaining fields - }; - - private final long[] mProcessFullStatsData = new long[2]; - - private static final int PROCESS_FULL_STAT_UTIME = 0; - private static final int PROCESS_FULL_STAT_STIME = 1; - - /** Used to read and parse {@code time_in_state} files */ - private final ProcTimeInStateReader mProcTimeInStateReader; private final int mPid; - /** Where the proc filesystem is mounted */ - private final Path mProcPath; + private final CpuTimeInStateReader mCpuTimeInStateReader; - // How long a CPU jiffy is in milliseconds. - private final long mJiffyMillis; + private int[] mSelectedThreadNativeTids = new int[0]; // Sorted - // Path: /proc/<pid>/stat - private final String mProcessStatFilePath; + /** + * Count of frequencies read from the {@code time_in_state} file. + */ + private int mFrequencyCount; - // Path: /proc/<pid>/task - private final Path mThreadsDirectoryPath; + private boolean mIsTracking; /** - * Count of frequencies read from the {@code time_in_state} file. Read from {@link - * #mProcTimeInStateReader#getCpuFrequenciesKhz()}. + * A CPU time-in-state provider for testing. Imitates the behavior of the corresponding + * methods in frameworks/native/libs/cputimeinstate/cputimeinstate.c */ - private int mFrequencyCount; + @VisibleForTesting + public interface CpuTimeInStateReader { + /** + * Returns the overall number of cluster-frequency combinations. + */ + int getCpuFrequencyCount(); + + /** + * Returns true to indicate success. + * + * Called from native. + */ + boolean startTrackingProcessCpuTimes(int tgid); + + /** + * Returns true to indicate success. + * + * Called from native. + */ + boolean startAggregatingTaskCpuTimes(int pid, int aggregationKey); + + /** + * Must return an array of strings formatted like this: + * "aggKey:t0_0 t0_1...:t1_0 t1_1..." + * Times should be provided in nanoseconds. + * + * Called from native. + */ + String[] getAggregatedTaskCpuFreqTimes(int pid); + } /** * Create with a path where `proc` is mounted. Used primarily for testing * * @param pid PID of the process whose threads are to be read. - * @param procPath where `proc` is mounted (to find, see {@code mount | grep ^proc}) */ @VisibleForTesting - public KernelSingleProcessCpuThreadReader( - int pid, - Path procPath) throws IOException { + public KernelSingleProcessCpuThreadReader(int pid, + @Nullable CpuTimeInStateReader cpuTimeInStateReader) throws IOException { mPid = pid; - mProcPath = procPath; - mProcTimeInStateReader = new ProcTimeInStateReader( - mProcPath.resolve(INITIAL_TIME_IN_STATE_PATH)); - long jiffyHz = Os.sysconf(OsConstants._SC_CLK_TCK); - mJiffyMillis = 1000 / jiffyHz; - mProcessStatFilePath = - mProcPath.resolve(String.valueOf(mPid)).resolve(PROC_STAT_FILENAME).toString(); - mThreadsDirectoryPath = - mProcPath.resolve(String.valueOf(mPid)).resolve(THREAD_CPU_STATS_DIRECTORY); + mCpuTimeInStateReader = cpuTimeInStateReader; } /** @@ -142,7 +103,7 @@ public class KernelSingleProcessCpuThreadReader { @Nullable public static KernelSingleProcessCpuThreadReader create(int pid) { try { - return new KernelSingleProcessCpuThreadReader(pid, DEFAULT_PROC_PATH); + return new KernelSingleProcessCpuThreadReader(pid, null); } catch (IOException e) { Slog.e(TAG, "Failed to initialize KernelSingleProcessCpuThreadReader", e); return null; @@ -150,146 +111,98 @@ public class KernelSingleProcessCpuThreadReader { } /** - * Get the CPU frequencies that correspond to the times reported in {@link - * ProcessCpuUsage#processCpuTimesMillis} etc. + * Starts tracking aggregated CPU time-in-state of all threads of the process with the PID + * supplied in the constructor. + */ + public void startTrackingThreadCpuTimes() { + if (!mIsTracking) { + if (!startTrackingProcessCpuTimes(mPid, mCpuTimeInStateReader)) { + Slog.e(TAG, "Failed to start tracking process CPU times for " + mPid); + } + if (mSelectedThreadNativeTids.length > 0) { + if (!startAggregatingThreadCpuTimes(mSelectedThreadNativeTids, + mCpuTimeInStateReader)) { + Slog.e(TAG, "Failed to start tracking aggregated thread CPU times for " + + Arrays.toString(mSelectedThreadNativeTids)); + } + } + mIsTracking = true; + } + } + + /** + * @param nativeTids an array of native Thread IDs whose CPU times should + * be aggregated as a group. This is expected to be a subset + * of all thread IDs owned by the process. + */ + public void setSelectedThreadIds(int[] nativeTids) { + mSelectedThreadNativeTids = nativeTids.clone(); + if (mIsTracking) { + startAggregatingThreadCpuTimes(mSelectedThreadNativeTids, mCpuTimeInStateReader); + } + } + + /** + * Get the CPU frequencies that correspond to the times reported in {@link ProcessCpuUsage}. */ public int getCpuFrequencyCount() { if (mFrequencyCount == 0) { - mFrequencyCount = mProcTimeInStateReader.getFrequenciesKhz().length; + mFrequencyCount = getCpuFrequencyCount(mCpuTimeInStateReader); } return mFrequencyCount; } /** - * Get the total and per-thread CPU usage of the process with the PID specified in the - * constructor. - * - * @param selectedThreadIds a SORTED array of native Thread IDs whose CPU times should - * be aggregated as a group. This is expected to be a subset - * of all thread IDs owned by the process. + * Get the total CPU usage of the process with the PID specified in the + * constructor. The CPU usage time is aggregated across all threads and may + * exceed the time the entire process has been running. */ @Nullable - public ProcessCpuUsage getProcessCpuUsage(int[] selectedThreadIds) { + public ProcessCpuUsage getProcessCpuUsage() { if (DEBUG) { - Slog.d(TAG, "Reading CPU thread usages with directory " + mProcPath + " process ID " - + mPid); - } - - int cpuFrequencyCount = getCpuFrequencyCount(); - ProcessCpuUsage processCpuUsage = new ProcessCpuUsage(cpuFrequencyCount); - - if (NATIVE_ENABLED) { - boolean result = readProcessCpuUsage(mProcPath.toString(), mPid, - selectedThreadIds, processCpuUsage.processCpuTimesMillis, - processCpuUsage.threadCpuTimesMillis, - processCpuUsage.selectedThreadCpuTimesMillis); - if (!result) { - return null; - } - return processCpuUsage; + Slog.d(TAG, "Reading CPU thread usages for PID " + mPid); } - if (!isSorted(selectedThreadIds)) { - throw new IllegalArgumentException("selectedThreadIds is not sorted: " - + Arrays.toString(selectedThreadIds)); - } - - if (!Process.readProcFile(mProcessStatFilePath, PROCESS_FULL_STATS_FORMAT, null, - mProcessFullStatsData, null)) { - Slog.e(TAG, "Failed to read process stat file " + mProcessStatFilePath); - return null; - } + ProcessCpuUsage processCpuUsage = new ProcessCpuUsage(getCpuFrequencyCount()); - long utime = mProcessFullStatsData[PROCESS_FULL_STAT_UTIME]; - long stime = mProcessFullStatsData[PROCESS_FULL_STAT_STIME]; - - long processCpuTimeMillis = (utime + stime) * mJiffyMillis; - - try (DirectoryStream<Path> threadPaths = Files.newDirectoryStream(mThreadsDirectoryPath)) { - for (Path threadDirectory : threadPaths) { - readThreadCpuUsage(processCpuUsage, selectedThreadIds, threadDirectory); - } - } catch (IOException | DirectoryIteratorException e) { - // Expected when a process finishes + boolean result = readProcessCpuUsage(mPid, + processCpuUsage.threadCpuTimesMillis, + processCpuUsage.selectedThreadCpuTimesMillis, + mCpuTimeInStateReader); + if (!result) { return null; } - // Estimate per cluster per frequency CPU time for the entire process - // by distributing the total process CPU time proportionately to how much - // CPU time its threads took on those clusters/frequencies. This algorithm - // works more accurately when when we have equally distributed concurrency. - // TODO(b/169279846): obtain actual process CPU times from the kernel - long totalCpuTimeAllThreads = 0; - for (int i = cpuFrequencyCount - 1; i >= 0; i--) { - totalCpuTimeAllThreads += processCpuUsage.threadCpuTimesMillis[i]; - } - - for (int i = cpuFrequencyCount - 1; i >= 0; i--) { - processCpuUsage.processCpuTimesMillis[i] = - processCpuTimeMillis * processCpuUsage.threadCpuTimesMillis[i] - / totalCpuTimeAllThreads; + if (DEBUG) { + Slog.d(TAG, "threadCpuTimesMillis = " + + Arrays.toString(processCpuUsage.threadCpuTimesMillis)); + Slog.d(TAG, "selectedThreadCpuTimesMillis = " + + Arrays.toString(processCpuUsage.selectedThreadCpuTimesMillis)); } return processCpuUsage; } - /** - * Reads a thread's CPU usage and aggregates the per-cluster per-frequency CPU times. - * - * @param threadDirectory the {@code /proc} directory of the thread - */ - private void readThreadCpuUsage(ProcessCpuUsage processCpuUsage, int[] selectedThreadIds, - Path threadDirectory) { - // Get the thread ID from the directory name - final int threadId; - try { - final String directoryName = threadDirectory.getFileName().toString(); - threadId = Integer.parseInt(directoryName); - } catch (NumberFormatException e) { - Slog.w(TAG, "Failed to parse thread ID when iterating over /proc/*/task", e); - return; - } - - // Get the CPU statistics from the directory - final Path threadCpuStatPath = threadDirectory.resolve(CPU_STATISTICS_FILENAME); - final long[] cpuUsages = mProcTimeInStateReader.getUsageTimesMillis(threadCpuStatPath); - if (cpuUsages == null) { - return; - } - - final int cpuFrequencyCount = getCpuFrequencyCount(); - final boolean isSelectedThread = Arrays.binarySearch(selectedThreadIds, threadId) >= 0; - for (int i = cpuFrequencyCount - 1; i >= 0; i--) { - processCpuUsage.threadCpuTimesMillis[i] += cpuUsages[i]; - if (isSelectedThread) { - processCpuUsage.selectedThreadCpuTimesMillis[i] += cpuUsages[i]; - } - } - } - /** CPU usage of a process, all of its threads and a selected subset of its threads */ public static class ProcessCpuUsage { - public long[] processCpuTimesMillis; public long[] threadCpuTimesMillis; public long[] selectedThreadCpuTimesMillis; public ProcessCpuUsage(int cpuFrequencyCount) { - processCpuTimesMillis = new long[cpuFrequencyCount]; threadCpuTimesMillis = new long[cpuFrequencyCount]; selectedThreadCpuTimesMillis = new long[cpuFrequencyCount]; } } - private static boolean isSorted(int[] array) { - for (int i = 0; i < array.length - 1; i++) { - if (array[i] > array[i + 1]) { - return false; - } - } - return true; - } + private native int getCpuFrequencyCount(CpuTimeInStateReader reader); + + private native boolean startTrackingProcessCpuTimes(int pid, CpuTimeInStateReader reader); + + private native boolean startAggregatingThreadCpuTimes(int[] selectedThreadIds, + CpuTimeInStateReader reader); - private native boolean readProcessCpuUsage(String procPath, int pid, int[] selectedThreadIds, - long[] processCpuTimesMillis, long[] threadCpuTimesMillis, - long[] selectedThreadCpuTimesMillis); + private native boolean readProcessCpuUsage(int pid, + long[] threadCpuTimesMillis, + long[] selectedThreadCpuTimesMillis, + CpuTimeInStateReader reader); } diff --git a/core/java/com/android/internal/os/OWNERS b/core/java/com/android/internal/os/OWNERS index afc94329dc4d..ae962f244a1a 100644 --- a/core/java/com/android/internal/os/OWNERS +++ b/core/java/com/android/internal/os/OWNERS @@ -1 +1,7 @@ -per-file ZygoteArguments.java,ZygoteConnection.java,ZygoteInit.java,Zygote.java,ZygoteServer.java = calin@google.com, chriswailes@google.com, maco@google.com, narayan@google.com, ngeoffray@google.com +per-file *Zygote* = file:/ZYGOTE_OWNERS + +# BatteryStats +per-file BatterySipper.java = file:/BATTERY_STATS_OWNERS +per-file BatteryStats* = file:/BATTERY_STATS_OWNERS +per-file BatteryUsageStats* = file:/BATTERY_STATS_OWNERS +per-file *PowerCalculator* = file:/BATTERY_STATS_OWNERS diff --git a/core/java/com/android/internal/os/PowerCalculator.java b/core/java/com/android/internal/os/PowerCalculator.java index f171b0d99acc..a57339b84b50 100644 --- a/core/java/com/android/internal/os/PowerCalculator.java +++ b/core/java/com/android/internal/os/PowerCalculator.java @@ -16,6 +16,8 @@ package com.android.internal.os; import android.os.BatteryStats; +import android.os.BatteryUsageStats; +import android.os.UidBatteryConsumer; import android.os.UserHandle; import android.util.SparseArray; @@ -55,6 +57,34 @@ public abstract class PowerCalculator { } /** + * Attributes the total amount of power used by this subsystem to various consumers such + * as apps. + * + * @param builder {@link BatteryUsageStats.Builder that contains a list of + * per-UID battery consumer builders for attribution data. + * The calculator may modify the builder and its constituent parts. + * @param batteryStats The recorded battery stats. + * @param rawRealtimeUs The raw system realtime in microseconds. + * @param rawUptimeUs The raw system uptime in microseconds. + * @param statsType The type of stats. As of {@link android.os.Build.VERSION_CODES#Q}, this + * can only be {@link BatteryStats#STATS_SINCE_CHARGED}, since + * {@link BatteryStats#STATS_CURRENT} and + * {@link BatteryStats#STATS_SINCE_UNPLUGGED} are deprecated. + * @param asUsers An array of users for which the attribution is requested. It may + * contain {@link UserHandle#USER_ALL} to indicate that the attribution + * should be performed for all users. + */ + public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats, + long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) { + final List<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders = + builder.getUidBatteryConsumerBuilders(); + for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) { + final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.get(i); + calculateApp(app, app.getBatteryStatsUid(), rawRealtimeUs, rawUptimeUs, statsType); + } + } + + /** * Calculate the amount of power an app used for this subsystem. * @param app The BatterySipper that represents the power use of an app. * @param u The recorded stats for the app. @@ -66,7 +96,36 @@ public abstract class PowerCalculator { * {@link BatteryStats#STATS_SINCE_UNPLUGGED} are deprecated. */ protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs, - long rawUptimeUs, int statsType) {} + long rawUptimeUs, int statsType) { + + // TODO(b/175156498): Temporary code during the transition from BatterySippers to + // BatteryConsumers. + UidBatteryConsumer.Builder builder = new UidBatteryConsumer.Builder(0, 0, u); + calculateApp(builder, u, rawRealtimeUs, rawUptimeUs, statsType); + final UidBatteryConsumer uidBatteryConsumer = builder.build(); + app.cpuPowerMah = uidBatteryConsumer.getConsumedPower( + UidBatteryConsumer.POWER_COMPONENT_CPU); + app.cpuTimeMs = uidBatteryConsumer.getUsageDurationMillis( + UidBatteryConsumer.TIME_COMPONENT_CPU); + app.cpuFgTimeMs = uidBatteryConsumer.getUsageDurationMillis( + UidBatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND); + app.packageWithHighestDrain = uidBatteryConsumer.getPackageWithHighestDrain(); + } + + /** + * Calculate the amount of power an app used for this subsystem. + * @param app The UidBatteryConsumer.Builder that represents the power use of an app. + * @param u The recorded stats for the app. + * @param rawRealtimeUs The raw system realtime in microseconds. + * @param rawUptimeUs The raw system uptime in microseconds. + * @param statsType The type of stats. As of {@link android.os.Build.VERSION_CODES#Q}, this can + * only be {@link BatteryStats#STATS_SINCE_CHARGED}, since + * {@link BatteryStats#STATS_CURRENT} and + * {@link BatteryStats#STATS_SINCE_UNPLUGGED} are deprecated. + */ + protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u, + long rawRealtimeUs, long rawUptimeUs, int statsType) { + } /** * Reset any state maintained in this calculator. diff --git a/core/java/com/android/internal/os/SystemServerCpuThreadReader.java b/core/java/com/android/internal/os/SystemServerCpuThreadReader.java index fbbee94feacc..fbad75e93a17 100644 --- a/core/java/com/android/internal/os/SystemServerCpuThreadReader.java +++ b/core/java/com/android/internal/os/SystemServerCpuThreadReader.java @@ -22,8 +22,6 @@ import android.os.Process; import com.android.internal.annotations.VisibleForTesting; import java.io.IOException; -import java.nio.file.Path; -import java.util.Arrays; /** * Reads /proc/UID/task/TID/time_in_state files to obtain statistics on CPU usage @@ -31,9 +29,7 @@ import java.util.Arrays; */ public class SystemServerCpuThreadReader { private final KernelSingleProcessCpuThreadReader mKernelCpuThreadReader; - private int[] mBinderThreadNativeTids = new int[0]; // Sorted - private long[] mLastProcessCpuTimeUs; private long[] mLastThreadCpuTimesUs; private long[] mLastBinderThreadCpuTimesUs; @@ -41,8 +37,6 @@ public class SystemServerCpuThreadReader { * Times (in microseconds) spent by the system server UID. */ public static class SystemServiceCpuThreadTimes { - // The entire process - public long[] processCpuTimesUs; // All threads public long[] threadCpuTimesUs; // Just the threads handling incoming binder calls @@ -61,8 +55,10 @@ public class SystemServerCpuThreadReader { } @VisibleForTesting - public SystemServerCpuThreadReader(Path procPath, int pid) throws IOException { - this(new KernelSingleProcessCpuThreadReader(pid, procPath)); + public SystemServerCpuThreadReader(int pid, + KernelSingleProcessCpuThreadReader.CpuTimeInStateReader cpuTimeInStateReader) + throws IOException { + this(new KernelSingleProcessCpuThreadReader(pid, cpuTimeInStateReader)); } @VisibleForTesting @@ -70,9 +66,15 @@ public class SystemServerCpuThreadReader { mKernelCpuThreadReader = kernelCpuThreadReader; } + /** + * Start tracking CPU time-in-state for the process specified in the constructor. + */ + public void startTrackingThreadCpuTime() { + mKernelCpuThreadReader.startTrackingThreadCpuTimes(); + } + public void setBinderThreadNativeTids(int[] nativeTids) { - mBinderThreadNativeTids = nativeTids.clone(); - Arrays.sort(mBinderThreadNativeTids); + mKernelCpuThreadReader.setSelectedThreadIds(nativeTids); } /** @@ -81,33 +83,27 @@ public class SystemServerCpuThreadReader { @Nullable public SystemServiceCpuThreadTimes readDelta() { final int numCpuFrequencies = mKernelCpuThreadReader.getCpuFrequencyCount(); - if (mLastProcessCpuTimeUs == null) { - mLastProcessCpuTimeUs = new long[numCpuFrequencies]; + if (mLastThreadCpuTimesUs == null) { mLastThreadCpuTimesUs = new long[numCpuFrequencies]; mLastBinderThreadCpuTimesUs = new long[numCpuFrequencies]; - mDeltaCpuThreadTimes.processCpuTimesUs = new long[numCpuFrequencies]; mDeltaCpuThreadTimes.threadCpuTimesUs = new long[numCpuFrequencies]; mDeltaCpuThreadTimes.binderThreadCpuTimesUs = new long[numCpuFrequencies]; } final KernelSingleProcessCpuThreadReader.ProcessCpuUsage processCpuUsage = - mKernelCpuThreadReader.getProcessCpuUsage(mBinderThreadNativeTids); + mKernelCpuThreadReader.getProcessCpuUsage(); if (processCpuUsage == null) { return null; } for (int i = numCpuFrequencies - 1; i >= 0; i--) { - long processCpuTimesUs = processCpuUsage.processCpuTimesMillis[i] * 1000; long threadCpuTimesUs = processCpuUsage.threadCpuTimesMillis[i] * 1000; long binderThreadCpuTimesUs = processCpuUsage.selectedThreadCpuTimesMillis[i] * 1000; - mDeltaCpuThreadTimes.processCpuTimesUs[i] = - Math.max(0, processCpuTimesUs - mLastProcessCpuTimeUs[i]); mDeltaCpuThreadTimes.threadCpuTimesUs[i] = Math.max(0, threadCpuTimesUs - mLastThreadCpuTimesUs[i]); mDeltaCpuThreadTimes.binderThreadCpuTimesUs[i] = Math.max(0, binderThreadCpuTimesUs - mLastBinderThreadCpuTimesUs[i]); - mLastProcessCpuTimeUs[i] = processCpuTimesUs; mLastThreadCpuTimesUs[i] = threadCpuTimesUs; mLastBinderThreadCpuTimesUs[i] = binderThreadCpuTimesUs; } diff --git a/core/java/com/android/internal/policy/OWNERS b/core/java/com/android/internal/policy/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/core/java/com/android/internal/policy/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/core/java/com/android/internal/statusbar/OWNERS b/core/java/com/android/internal/statusbar/OWNERS new file mode 100644 index 000000000000..2e96c97c8bb3 --- /dev/null +++ b/core/java/com/android/internal/statusbar/OWNERS @@ -0,0 +1 @@ +include /packages/SystemUI/OWNERS diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl index c2cbc04fcee5..303365b4ab3b 100644 --- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -94,4 +94,5 @@ interface ITelephonyRegistry { void notifyBarringInfoChanged(int slotIndex, int subId, in BarringInfo barringInfo); void notifyPhysicalChannelConfigForSubscriber(in int subId, in List<PhysicalChannelConfig> configs); + void notifyDataEnabled(boolean enabled, int reason); } diff --git a/core/java/com/android/internal/util/BinaryXmlPullParser.java b/core/java/com/android/internal/util/BinaryXmlPullParser.java index ff7743fbe361..68921ade3080 100644 --- a/core/java/com/android/internal/util/BinaryXmlPullParser.java +++ b/core/java/com/android/internal/util/BinaryXmlPullParser.java @@ -414,29 +414,21 @@ public final class BinaryXmlPullParser implements TypedXmlPullParser { mAttributeCount = 0; } - /** - * Search through the pool of currently allocated {@link Attribute} - * instances for one that matches the given name. - */ - private @NonNull Attribute findAttribute(@NonNull String name) - throws XmlPullParserException { + @Override + public int getAttributeIndex(String namespace, String name) { + if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); for (int i = 0; i < mAttributeCount; i++) { if (Objects.equals(mAttributes[i].name, name)) { - return mAttributes[i]; + return i; } } - throw new XmlPullParserException("Missing attribute " + name); + return -1; } @Override public String getAttributeValue(String namespace, String name) { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - try { - return findAttribute(name).getValueString(); - } catch (XmlPullParserException e) { - // Missing attributes default to null - return null; - } + final int index = getAttributeIndex(namespace, name); + return mAttributes[index].getValueString(); } @Override @@ -445,66 +437,48 @@ public final class BinaryXmlPullParser implements TypedXmlPullParser { } @Override - public byte[] getAttributeBytesHex(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueBytesHex(); + public byte[] getAttributeBytesHex(int index) throws XmlPullParserException { + return mAttributes[index].getValueBytesHex(); } @Override - public byte[] getAttributeBytesBase64(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueBytesBase64(); + public byte[] getAttributeBytesBase64(int index) throws XmlPullParserException { + return mAttributes[index].getValueBytesBase64(); } @Override - public int getAttributeInt(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueInt(); + public int getAttributeInt(int index) throws XmlPullParserException { + return mAttributes[index].getValueInt(); } @Override - public int getAttributeIntHex(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueIntHex(); + public int getAttributeIntHex(int index) throws XmlPullParserException { + return mAttributes[index].getValueIntHex(); } @Override - public long getAttributeLong(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueLong(); + public long getAttributeLong(int index) throws XmlPullParserException { + return mAttributes[index].getValueLong(); } @Override - public long getAttributeLongHex(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueLongHex(); + public long getAttributeLongHex(int index) throws XmlPullParserException { + return mAttributes[index].getValueLongHex(); } @Override - public float getAttributeFloat(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueFloat(); + public float getAttributeFloat(int index) throws XmlPullParserException { + return mAttributes[index].getValueFloat(); } @Override - public double getAttributeDouble(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueDouble(); + public double getAttributeDouble(int index) throws XmlPullParserException { + return mAttributes[index].getValueDouble(); } @Override - public boolean getAttributeBoolean(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueBoolean(); + public boolean getAttributeBoolean(int index) throws XmlPullParserException { + return mAttributes[index].getValueBoolean(); } @Override diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java index 244efc596926..de6b65f36eed 100644 --- a/core/java/com/android/internal/util/XmlUtils.java +++ b/core/java/com/android/internal/util/XmlUtils.java @@ -142,95 +142,104 @@ public class XmlUtils { } @Override - public byte[] getAttributeBytesHex(String namespace, String name) + public byte[] getAttributeBytesHex(int index) throws XmlPullParserException { try { - return HexDump.hexStringToByteArray(getAttributeValue(namespace, name)); + return HexDump.hexStringToByteArray(getAttributeValue(index)); } catch (Exception e) { - throw new XmlPullParserException("Invalid attribute " + name + ": " + e); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + e); } } @Override - public byte[] getAttributeBytesBase64(String namespace, String name) + public byte[] getAttributeBytesBase64(int index) throws XmlPullParserException { try { - return Base64.decode(getAttributeValue(namespace, name), Base64.NO_WRAP); + return Base64.decode(getAttributeValue(index), Base64.NO_WRAP); } catch (Exception e) { - throw new XmlPullParserException("Invalid attribute " + name + ": " + e); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + e); } } @Override - public int getAttributeInt(String namespace, String name) + public int getAttributeInt(int index) throws XmlPullParserException { try { - return Integer.parseInt(getAttributeValue(namespace, name)); + return Integer.parseInt(getAttributeValue(index)); } catch (Exception e) { - throw new XmlPullParserException("Invalid attribute " + name + ": " + e); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + e); } } @Override - public int getAttributeIntHex(String namespace, String name) + public int getAttributeIntHex(int index) throws XmlPullParserException { try { - return Integer.parseInt(getAttributeValue(namespace, name), 16); + return Integer.parseInt(getAttributeValue(index), 16); } catch (Exception e) { - throw new XmlPullParserException("Invalid attribute " + name + ": " + e); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + e); } } @Override - public long getAttributeLong(String namespace, String name) + public long getAttributeLong(int index) throws XmlPullParserException { try { - return Long.parseLong(getAttributeValue(namespace, name)); + return Long.parseLong(getAttributeValue(index)); } catch (Exception e) { - throw new XmlPullParserException("Invalid attribute " + name + ": " + e); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + e); } } @Override - public long getAttributeLongHex(String namespace, String name) + public long getAttributeLongHex(int index) throws XmlPullParserException { try { - return Long.parseLong(getAttributeValue(namespace, name), 16); + return Long.parseLong(getAttributeValue(index), 16); } catch (Exception e) { - throw new XmlPullParserException("Invalid attribute " + name + ": " + e); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + e); } } @Override - public float getAttributeFloat(String namespace, String name) + public float getAttributeFloat(int index) throws XmlPullParserException { try { - return Float.parseFloat(getAttributeValue(namespace, name)); + return Float.parseFloat(getAttributeValue(index)); } catch (Exception e) { - throw new XmlPullParserException("Invalid attribute " + name + ": " + e); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + e); } } @Override - public double getAttributeDouble(String namespace, String name) + public double getAttributeDouble(int index) throws XmlPullParserException { try { - return Double.parseDouble(getAttributeValue(namespace, name)); + return Double.parseDouble(getAttributeValue(index)); } catch (Exception e) { - throw new XmlPullParserException("Invalid attribute " + name + ": " + e); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + e); } } @Override - public boolean getAttributeBoolean(String namespace, String name) + public boolean getAttributeBoolean(int index) throws XmlPullParserException { - final String value = getAttributeValue(namespace, name); + final String value = getAttributeValue(index); if ("true".equalsIgnoreCase(value)) { return true; } else if ("false".equalsIgnoreCase(value)) { return false; } else { - throw new XmlPullParserException("Invalid attribute " + name + ": " + value); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + value); } } } diff --git a/core/jni/OWNERS b/core/jni/OWNERS index 7d80993afc6e..bcd1278d87e7 100644 --- a/core/jni/OWNERS +++ b/core/jni/OWNERS @@ -16,5 +16,21 @@ per-file android_view_*KeyEvent.* = michaelwr@google.com, svv@google.com per-file android_view_*MotionEvent.* = michaelwr@google.com, svv@google.com per-file android_view_PointerIcon.* = michaelwr@google.com, svv@google.com -# Zygote -per-file com_android_internal_os_Zygote.*,fd_utils.* = calin@google.com, chriswailes@google.com, maco@google.com, narayan@google.com, ngeoffray@google.com +per-file *Zygote* = file:/ZYGOTE_OWNERS +per-file Android.bp = file:platform/build/soong:/OWNERS +per-file android_animation_* = file:/core/java/android/animation/OWNERS +per-file android_app_admin_* = file:/core/java/android/app/admin/OWNERS +per-file android_content_res_* = file:/core/java/android/content/res/OWNERS +per-file android_graphics_* = file:/graphics/java/android/graphics/OWNERS +per-file android_hardware_Usb* = file:/services/usb/OWNERS +per-file android_hardware_display_* = file:/core/java/android/hardware/display/OWNERS +per-file android_hardware_input_* = file:/core/java/android/hardware/input/OWNERS +per-file android_hardware_location_* = file:/core/java/android/hardware/location/OWNERS +per-file android_media_* = file:/media/java/android/media/OWNERS +per-file android_media_midi_* = file:/media/java/android/media/midi/OWNERS +per-file android_opengl_* = file:/opengl/java/android/opengl/OWNERS +per-file android_os_storage_* = file:/core/java/android/os/storage/OWNERS +per-file android_se_* = file:/core/java/android/se/OWNERS +per-file android_security_* = file:/core/java/android/security/OWNERS +per-file android_view_* = file:/core/java/android/view/OWNERS +per-file com_android_internal_net_* = file:/services/core/java/com/android/server/net/OWNERS diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 1ca45fe9f70b..b1b0284e5295 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -48,8 +48,9 @@ static const char* const kClassPathName = "android/media/AudioSystem"; static jclass gArrayListClass; static struct { - jmethodID add; - jmethodID toArray; + jmethodID cstor; + jmethodID add; + jmethodID toArray; } gArrayListMethods; static jclass gBooleanClass; @@ -185,6 +186,9 @@ jmethodID gMidAudioRecordRoutingProxy_release; jclass gClsAudioTrackRoutingProxy; jclass gClsAudioRecordRoutingProxy; +jclass gAudioProfileClass; +jmethodID gAudioProfileCstor; + static Mutex gLock; enum AudioError { @@ -807,13 +811,6 @@ android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz) return (jint) check_AudioSystem_Command(AudioSystem::checkAudioFlinger()); } - -static bool useInChannelMask(audio_port_type_t type, audio_port_role_t role) -{ - return ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) || - ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK)); -} - static void convertAudioGainConfigToNative(JNIEnv *env, struct audio_gain_config *nAudioGainConfig, const jobject jAudioGainConfig, @@ -873,7 +870,7 @@ static jint convertAudioPortConfigToNative(JNIEnv *env, configMask |= AUDIO_PORT_CONFIG_SAMPLE_RATE; } - bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role); + bool useInMask = audio_port_config_has_input_direction(nAudioPortConfig); audio_channel_mask_t nMask; jint jMask = env->GetIntField(jAudioPortConfig, gAudioPortConfigFields.mChannelMask); @@ -1000,7 +997,7 @@ static jint convertAudioPortConfigFromNative(JNIEnv *env, audioportCreated = true; } - bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role); + bool useInMask = audio_port_config_has_input_direction(nAudioPortConfig); audio_channel_mask_t nMask; jint jMask; @@ -1137,15 +1134,6 @@ exit: return jStatus; } -static bool hasFormat(int* formats, size_t size, int format) { - for (size_t index = 0; index < size; index++) { - if (formats[index] == format) { - return true; // found - } - } - return false; // not found -} - // TODO: pull out to separate file template <typename T, size_t N> static constexpr size_t array_size(const T (&)[N]) { @@ -1167,43 +1155,46 @@ static jintArray convertEncapsulationInfoFromNative(JNIEnv *env, uint32_t encaps return result; } -static jint convertAudioPortFromNative(JNIEnv *env, - jobject *jAudioPort, const struct audio_port *nAudioPort) -{ +static bool isAudioPortArrayCountOutOfBounds(const struct audio_port_v7 *nAudioPort, + std::stringstream &ss) { + ss << " num_audio_profiles " << nAudioPort->num_audio_profiles << " num_gains " + << nAudioPort->num_gains; + if (nAudioPort->num_audio_profiles > array_size(nAudioPort->audio_profiles) || + nAudioPort->num_gains > array_size(nAudioPort->gains)) { + return true; + } + for (size_t i = 0; i < nAudioPort->num_audio_profiles; ++i) { + ss << " (" << i << ") audio profile," + << " num_sample_rates " << nAudioPort->audio_profiles[i].num_sample_rates + << " num_channel_masks " << nAudioPort->audio_profiles[i].num_channel_masks; + if (nAudioPort->audio_profiles[i].num_sample_rates > + array_size(nAudioPort->audio_profiles[i].sample_rates) || + nAudioPort->audio_profiles[i].num_channel_masks > + array_size(nAudioPort->audio_profiles[i].channel_masks)) { + return true; + } + } + return false; +} + +static jint convertAudioPortFromNative(JNIEnv *env, jobject *jAudioPort, + const struct audio_port_v7 *nAudioPort) { jint jStatus = (jint)AUDIO_JAVA_SUCCESS; - jintArray jSamplingRates = NULL; - jintArray jChannelMasks = NULL; - jintArray jChannelIndexMasks = NULL; jintArray jEncapsulationModes = NULL; jintArray jEncapsulationMetadataTypes = NULL; - int* cFormats = NULL; - jintArray jFormats = NULL; jobjectArray jGains = NULL; jobject jHandle = NULL; jobject jAudioPortConfig = NULL; jstring jDeviceName = NULL; + jobject jAudioProfiles = NULL; bool useInMask; - size_t numPositionMasks = 0; - size_t numIndexMasks = 0; - size_t numUniqueFormats = 0; ALOGV("convertAudioPortFromNative id %d role %d type %d name %s", nAudioPort->id, nAudioPort->role, nAudioPort->type, nAudioPort->name); // Verify audio port array count info. - if (nAudioPort->num_sample_rates > array_size(nAudioPort->sample_rates) - || nAudioPort->num_channel_masks > array_size(nAudioPort->channel_masks) - || nAudioPort->num_formats > array_size(nAudioPort->formats) - || nAudioPort->num_gains > array_size(nAudioPort->gains)) { - - std::stringstream ss; - ss << "convertAudioPortFromNative array count out of bounds:" - << " num_sample_rates " << nAudioPort->num_sample_rates - << " num_channel_masks " << nAudioPort->num_channel_masks - << " num_formats " << nAudioPort->num_formats - << " num_gains " << nAudioPort->num_gains - ; - std::string s = ss.str(); + if (std::stringstream ss; isAudioPortArrayCountOutOfBounds(nAudioPort, ss)) { + std::string s = "convertAudioPortFromNative array count out of bounds:" + ss.str(); // Prefer to log through Java wtf instead of native ALOGE. ScopedLocalRef<jclass> jLogClass(env, env->FindClass("android/util/Log")); @@ -1222,69 +1213,68 @@ static jint convertAudioPortFromNative(JNIEnv *env, goto exit; } - jSamplingRates = env->NewIntArray(nAudioPort->num_sample_rates); - if (jSamplingRates == NULL) { + useInMask = audio_has_input_direction(nAudioPort->type, nAudioPort->role); + jAudioProfiles = env->NewObject(gArrayListClass, gArrayListMethods.cstor); + if (jAudioProfiles == nullptr) { jStatus = (jint)AUDIO_JAVA_ERROR; goto exit; } - if (nAudioPort->num_sample_rates) { - env->SetIntArrayRegion(jSamplingRates, 0, nAudioPort->num_sample_rates, - (jint *)nAudioPort->sample_rates); - } - - // count up how many masks are positional and indexed - for(size_t index = 0; index < nAudioPort->num_channel_masks; index++) { - const audio_channel_mask_t mask = nAudioPort->channel_masks[index]; - if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) { - numIndexMasks++; - } else { - numPositionMasks++; + for (size_t i = 0; i < nAudioPort->num_audio_profiles; ++i) { + size_t numPositionMasks = 0; + size_t numIndexMasks = 0; + // count up how many masks are positional and indexed + for (size_t index = 0; index < nAudioPort->audio_profiles[i].num_channel_masks; index++) { + const audio_channel_mask_t mask = nAudioPort->audio_profiles[i].channel_masks[index]; + if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) { + numIndexMasks++; + } else { + numPositionMasks++; + } } - } - jChannelMasks = env->NewIntArray(numPositionMasks); - if (jChannelMasks == NULL) { - jStatus = (jint)AUDIO_JAVA_ERROR; - goto exit; - } - jChannelIndexMasks = env->NewIntArray(numIndexMasks); - if (jChannelIndexMasks == NULL) { - jStatus = (jint)AUDIO_JAVA_ERROR; - goto exit; - } - useInMask = useInChannelMask(nAudioPort->type, nAudioPort->role); + ScopedLocalRef<jintArray> jSamplingRates(env, + env->NewIntArray(nAudioPort->audio_profiles[i] + .num_sample_rates)); + ScopedLocalRef<jintArray> jChannelMasks(env, env->NewIntArray(numPositionMasks)); + ScopedLocalRef<jintArray> jChannelIndexMasks(env, env->NewIntArray(numIndexMasks)); + if (!jSamplingRates.get() || !jChannelMasks.get() || !jChannelIndexMasks.get()) { + jStatus = (jint)AUDIO_JAVA_ERROR; + goto exit; + } - // put the masks in the output arrays - for (size_t maskIndex = 0, posMaskIndex = 0, indexedMaskIndex = 0; - maskIndex < nAudioPort->num_channel_masks; maskIndex++) { - const audio_channel_mask_t mask = nAudioPort->channel_masks[maskIndex]; - if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) { - jint jMask = audio_channel_mask_get_bits(mask); - env->SetIntArrayRegion(jChannelIndexMasks, indexedMaskIndex++, 1, &jMask); - } else { - jint jMask = useInMask ? inChannelMaskFromNative(mask) - : outChannelMaskFromNative(mask); - env->SetIntArrayRegion(jChannelMasks, posMaskIndex++, 1, &jMask); + if (nAudioPort->audio_profiles[i].num_sample_rates) { + env->SetIntArrayRegion(jSamplingRates.get(), 0 /*start*/, + nAudioPort->audio_profiles[i].num_sample_rates, + (jint *)nAudioPort->audio_profiles[i].sample_rates); } - } - // formats - if (nAudioPort->num_formats != 0) { - cFormats = new int[nAudioPort->num_formats]; - for (size_t index = 0; index < nAudioPort->num_formats; index++) { - int format = audioFormatFromNative(nAudioPort->formats[index]); - if (!hasFormat(cFormats, numUniqueFormats, format)) { - cFormats[numUniqueFormats++] = format; + // put the masks in the output arrays + for (size_t maskIndex = 0, posMaskIndex = 0, indexedMaskIndex = 0; + maskIndex < nAudioPort->audio_profiles[i].num_channel_masks; maskIndex++) { + const audio_channel_mask_t mask = + nAudioPort->audio_profiles[i].channel_masks[maskIndex]; + if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) { + jint jMask = audio_channel_mask_get_bits(mask); + env->SetIntArrayRegion(jChannelIndexMasks.get(), indexedMaskIndex++, 1, &jMask); + } else { + jint jMask = + useInMask ? inChannelMaskFromNative(mask) : outChannelMaskFromNative(mask); + env->SetIntArrayRegion(jChannelMasks.get(), posMaskIndex++, 1, &jMask); } } - } - jFormats = env->NewIntArray(numUniqueFormats); - if (jFormats == NULL) { - jStatus = (jint)AUDIO_JAVA_ERROR; - goto exit; - } - if (numUniqueFormats != 0) { - env->SetIntArrayRegion(jFormats, 0, numUniqueFormats, cFormats); + + ScopedLocalRef<jobject> + jAudioProfile(env, + env->NewObject(gAudioProfileClass, gAudioProfileCstor, + audioFormatFromNative( + nAudioPort->audio_profiles[i].format), + jSamplingRates.get(), jChannelMasks.get(), + jChannelIndexMasks.get())); + if (jAudioProfile == nullptr) { + jStatus = (jint)AUDIO_JAVA_ERROR; + goto exit; + } + env->CallBooleanMethod(jAudioProfiles, gArrayListMethods.add, jAudioProfile.get()); } // gains @@ -1342,18 +1332,16 @@ static jint convertAudioPortFromNative(JNIEnv *env, convertEncapsulationInfoFromNative(env, nAudioPort->ext.device .encapsulation_metadata_types); - *jAudioPort = env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor, jHandle, - jDeviceName, jSamplingRates, jChannelMasks, jChannelIndexMasks, - jFormats, jGains, nAudioPort->ext.device.type, jAddress, - jEncapsulationModes, jEncapsulationMetadataTypes); + *jAudioPort = + env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor, jHandle, jDeviceName, + jAudioProfiles, jGains, nAudioPort->ext.device.type, jAddress, + jEncapsulationModes, jEncapsulationMetadataTypes); env->DeleteLocalRef(jAddress); } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) { ALOGV("convertAudioPortFromNative is a mix"); - *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor, - jHandle, nAudioPort->ext.mix.handle, - nAudioPort->role, jDeviceName, - jSamplingRates, jChannelMasks, jChannelIndexMasks, - jFormats, jGains); + *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor, jHandle, + nAudioPort->ext.mix.handle, nAudioPort->role, jDeviceName, + jAudioProfiles, jGains); } else { ALOGE("convertAudioPortFromNative unknown nAudioPort type %d", nAudioPort->type); jStatus = (jint)AUDIO_JAVA_ERROR; @@ -1378,26 +1366,14 @@ exit: if (jDeviceName != NULL) { env->DeleteLocalRef(jDeviceName); } - if (jSamplingRates != NULL) { - env->DeleteLocalRef(jSamplingRates); - } - if (jChannelMasks != NULL) { - env->DeleteLocalRef(jChannelMasks); - } - if (jChannelIndexMasks != NULL) { - env->DeleteLocalRef(jChannelIndexMasks); - } if (jEncapsulationModes != NULL) { env->DeleteLocalRef(jEncapsulationModes); } if (jEncapsulationMetadataTypes != NULL) { env->DeleteLocalRef(jEncapsulationMetadataTypes); } - if (cFormats != NULL) { - delete[] cFormats; - } - if (jFormats != NULL) { - env->DeleteLocalRef(jFormats); + if (jAudioProfiles != NULL) { + env->DeleteLocalRef(jAudioProfiles); } if (jGains != NULL) { env->DeleteLocalRef(jGains); @@ -1436,7 +1412,7 @@ android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz, unsigned int generation; unsigned int numPorts; jint *nGeneration; - struct audio_port *nPorts = NULL; + struct audio_port_v7 *nPorts = nullptr; int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS; jint jStatus; @@ -1448,11 +1424,8 @@ android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz, } numPorts = 0; - status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE, - AUDIO_PORT_TYPE_NONE, - &numPorts, - NULL, - &generation1); + status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_NONE, &numPorts, + nullptr, &generation1); if (status != NO_ERROR) { ALOGE_IF(status != NO_ERROR, "AudioSystem::listAudioPorts error %d", status); break; @@ -1461,13 +1434,10 @@ android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz, jStatus = (jint)AUDIO_JAVA_SUCCESS; goto exit; } - nPorts = (struct audio_port *)realloc(nPorts, numPorts * sizeof(struct audio_port)); + nPorts = (struct audio_port_v7 *)realloc(nPorts, numPorts * sizeof(struct audio_port_v7)); - status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE, - AUDIO_PORT_TYPE_NONE, - &numPorts, - nPorts, - &generation); + status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_NONE, &numPorts, + nPorts, &generation); ALOGV("listAudioPorts AudioSystem::listAudioPorts numPorts %d generation %d generation1 %d", numPorts, generation, generation1); } while (generation1 != generation && status == NO_ERROR); @@ -2671,6 +2641,7 @@ int register_android_media_AudioSystem(JNIEnv *env) jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList"); gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass); + gArrayListMethods.cstor = GetMethodIDOrDie(env, arrayListClass, "<init>", "()V"); gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z"); gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass, "toArray", "()[Ljava/lang/Object;"); @@ -2733,7 +2704,7 @@ int register_android_media_AudioSystem(JNIEnv *env) gAudioDevicePortClass = MakeGlobalRefOrDie(env, audioDevicePortClass); gAudioDevicePortCstor = GetMethodIDOrDie(env, audioDevicePortClass, "<init>", - "(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I" + "(Landroid/media/AudioHandle;Ljava/lang/String;Ljava/util/List;" "[Landroid/media/AudioGain;ILjava/lang/String;[I[I)V"); // When access AudioPort as AudioDevicePort @@ -2743,8 +2714,10 @@ int register_android_media_AudioSystem(JNIEnv *env) jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort"); gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass); - gAudioMixPortCstor = GetMethodIDOrDie(env, audioMixPortClass, "<init>", - "(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V"); + gAudioMixPortCstor = + GetMethodIDOrDie(env, audioMixPortClass, "<init>", + "(Landroid/media/AudioHandle;IILjava/lang/String;Ljava/util/List;" + "[Landroid/media/AudioGain;)V"); jclass audioGainClass = FindClassOrDie(env, "android/media/AudioGain"); gAudioGainClass = MakeGlobalRefOrDie(env, audioGainClass); @@ -2846,6 +2819,10 @@ int register_android_media_AudioSystem(JNIEnv *env) jclass listClass = FindClassOrDie(env, "java/util/List"); gListMethods.add = GetMethodIDOrDie(env, listClass, "add", "(Ljava/lang/Object;)Z"); + jclass audioProfileClass = FindClassOrDie(env, "android/media/AudioProfile"); + gAudioProfileClass = MakeGlobalRefOrDie(env, audioProfileClass); + gAudioProfileCstor = GetMethodIDOrDie(env, audioProfileClass, "<init>", "(I[I[I[I)V"); + AudioSystem::addErrorCallback(android_media_AudioSystem_error_callback); RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 6ec656c16790..a21545c21011 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -52,6 +52,7 @@ #include <ui/Rect.h> #include <ui/Region.h> #include <utils/Log.h> +#include <utils/LightRefBase.h> // ---------------------------------------------------------------------------- @@ -206,6 +207,16 @@ static struct { jfieldID appRequestRefreshRateMax; } gDesiredDisplayConfigSpecsClassInfo; +static struct { + jclass clazz; + jmethodID onJankDataAvailable; +} gJankDataListenerClassInfo; + +static struct { + jclass clazz; + jmethodID ctor; +} gJankDataClassInfo; + class JNamedColorSpace { public: // ColorSpace.Named.SRGB.ordinal() = 0; @@ -1601,6 +1612,73 @@ static void nativeSetFrameTimelineVsync(JNIEnv* env, jclass clazz, jlong transac transaction->setFrameTimelineVsync(frameTimelineVsyncId); } +class JankDataListenerWrapper : public JankDataListener { +public: + JankDataListenerWrapper(JNIEnv* env, jobject onJankDataListenerObject) { + mOnJankDataListenerWeak = env->NewWeakGlobalRef(onJankDataListenerObject); + env->GetJavaVM(&mVm); + } + + ~JankDataListenerWrapper() { + JNIEnv* env = getEnv(); + env->DeleteWeakGlobalRef(mOnJankDataListenerWeak); + } + + void onJankDataAvailable(const std::vector<JankData>& jankData) { + JNIEnv* env = getEnv(); + + jobject target = env->NewLocalRef(mOnJankDataListenerWeak); + if (target == nullptr) return; + + jobjectArray jJankDataArray = env->NewObjectArray(jankData.size(), + gJankDataClassInfo.clazz, nullptr); + for (int i = 0; i < jankData.size(); i++) { + jobject jJankData = env->NewObject(gJankDataClassInfo.clazz, + gJankDataClassInfo.ctor, jankData[i].frameVsyncId, jankData[i].jankType); + env->SetObjectArrayElement(jJankDataArray, i, jJankData); + } + env->CallVoidMethod(target, + gJankDataListenerClassInfo.onJankDataAvailable, + jJankDataArray); + env->DeleteLocalRef(target); + } + +private: + + JNIEnv* getEnv() { + JNIEnv* env; + mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6); + return env; + } + + JavaVM* mVm; + jobject mOnJankDataListenerWeak; +}; + +static void nativeAddJankDataListener(JNIEnv* env, jclass clazz, + jlong jankDataCallbackListenerPtr, + jlong nativeSurfaceControl) { + sp<SurfaceControl> surface(reinterpret_cast<SurfaceControl *>(nativeSurfaceControl)); + if (surface == nullptr) { + return; + } + JankDataListenerWrapper* wrapper = + reinterpret_cast<JankDataListenerWrapper*>(jankDataCallbackListenerPtr); + TransactionCompletedListener::getInstance()->addJankListener(wrapper, surface); +} + +static void nativeRemoveJankDataListener(JNIEnv* env, jclass clazz, + jlong jankDataCallbackListenerPtr) { + JankDataListenerWrapper* wrapper = + reinterpret_cast<JankDataListenerWrapper*>(jankDataCallbackListenerPtr); + TransactionCompletedListener::getInstance()->removeJankListener(wrapper); +} + +static jlong nativeCreateJankDataListenerWrapper(JNIEnv* env, jclass clazz, + jobject jankDataListenerObject) { + return reinterpret_cast<jlong>(new JankDataListenerWrapper(env, jankDataListenerObject)); +} + // ---------------------------------------------------------------------------- static const JNINativeMethod sSurfaceControlMethods[] = { @@ -1785,6 +1863,12 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetFocusedWindow}, {"nativeSetFrameTimelineVsync", "(JJ)V", (void*)nativeSetFrameTimelineVsync }, + {"nativeAddJankDataListener", "(JJ)V", + (void*)nativeAddJankDataListener }, + {"nativeRemoveJankDataListener", "(J)V", + (void*)nativeRemoveJankDataListener }, + {"nativeCreateJankDataListenerWrapper", "(Landroid/view/SurfaceControl$OnJankDataListener;)J", + (void*)nativeCreateJankDataListenerWrapper }, // clang-format on }; @@ -1966,6 +2050,18 @@ int register_android_view_SurfaceControl(JNIEnv* env) gScreenCaptureListenerClassInfo.onScreenCaptureComplete = GetMethodIDOrDie(env, screenCaptureListenerClazz, "onScreenCaptureComplete", "(Landroid/view/SurfaceControl$ScreenshotHardwareBuffer;)V"); + + jclass jankDataClazz = + FindClassOrDie(env, "android/view/SurfaceControl$JankData"); + gJankDataClassInfo.clazz = MakeGlobalRefOrDie(env, jankDataClazz); + gJankDataClassInfo.ctor = + GetMethodIDOrDie(env, gJankDataClassInfo.clazz, "<init>", "(JI)V"); + jclass onJankDataListenerClazz = + FindClassOrDie(env, "android/view/SurfaceControl$OnJankDataListener"); + gJankDataListenerClassInfo.clazz = MakeGlobalRefOrDie(env, onJankDataListenerClazz); + gJankDataListenerClassInfo.onJankDataAvailable = + GetMethodIDOrDie(env, onJankDataListenerClazz, "onJankDataAvailable", + "([Landroid/view/SurfaceControl$JankData;)V"); return err; } diff --git a/core/jni/com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp b/core/jni/com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp index 52bed6bcfce3..dfae68429f6d 100644 --- a/core/jni/com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp +++ b/core/jni/com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp @@ -26,244 +26,308 @@ #include <android_runtime/Log.h> #include <nativehelper/ScopedPrimitiveArray.h> -#include <nativehelper/ScopedUtfChars.h> namespace android { +static constexpr uint16_t DEFAULT_THREAD_AGGREGATION_KEY = 0; +static constexpr uint16_t SELECTED_THREAD_AGGREGATION_KEY = 1; + +static constexpr uint64_t NSEC_PER_MSEC = 1000000; + // Number of milliseconds in a jiffy - the unit of time measurement for processes and threads static const uint32_t gJiffyMillis = (uint32_t)(1000 / sysconf(_SC_CLK_TCK)); -// Given a PID, returns a vector of all TIDs for the process' tasks. Thread IDs are -// file names in the /proc/<pid>/task directory. -static bool getThreadIds(const std::string &procPath, const pid_t pid, - std::vector<pid_t> &outThreadIds) { - std::string taskPath = android::base::StringPrintf("%s/%u/task", procPath.c_str(), pid); +// Abstract class for readers of CPU time-in-state. There are two implementations of +// this class: BpfCpuTimeInStateReader and MockCpuTimeInStateReader. The former is used +// by the production code. The latter is used by unit tests to provide mock +// CPU time-in-state data via a Java implementation. +class ICpuTimeInStateReader { +public: + virtual ~ICpuTimeInStateReader() {} + + // Returns the overall number of cluser-frequency combinations + virtual size_t getCpuFrequencyCount(); + + // Marks the CPU time-in-state tracking for threads of the specified TGID + virtual bool startTrackingProcessCpuTimes(pid_t) = 0; + + // Marks the thread specified by its PID for CPU time-in-state tracking. + virtual bool startAggregatingTaskCpuTimes(pid_t, uint16_t) = 0; + + // Retrieves the accumulated time-in-state data, which is organized as a map + // from aggregation keys to vectors of vectors using the format: + // { aggKey0 -> [[t0_0_0, t0_0_1, ...], [t0_1_0, t0_1_1, ...], ...], + // aggKey1 -> [[t1_0_0, t1_0_1, ...], [t1_1_0, t1_1_1, ...], ...], ... } + // where ti_j_k is the ns tid i spent running on the jth cluster at the cluster's kth lowest + // freq. + virtual std::optional<std::unordered_map<uint16_t, std::vector<std::vector<uint64_t>>>> + getAggregatedTaskCpuFreqTimes(pid_t, const std::vector<uint16_t> &); +}; - struct dirent **dirlist; - int threadCount = scandir(taskPath.c_str(), &dirlist, NULL, NULL); - if (threadCount == -1) { - ALOGE("Cannot read directory %s", taskPath.c_str()); - return false; +// ICpuTimeInStateReader that uses eBPF to provide a map of aggregated CPU time-in-state values. +// See cputtimeinstate.h/.cpp +class BpfCpuTimeInStateReader : public ICpuTimeInStateReader { +public: + size_t getCpuFrequencyCount() { + std::optional<std::vector<std::vector<uint32_t>>> cpuFreqs = android::bpf::getCpuFreqs(); + if (!cpuFreqs) { + ALOGE("Cannot obtain CPU frequency count"); + return 0; + } + + size_t freqCount = 0; + for (auto cluster : *cpuFreqs) { + freqCount += cluster.size(); + } + + return freqCount; } - outThreadIds.reserve(threadCount); + bool startTrackingProcessCpuTimes(pid_t tgid) { + return android::bpf::startTrackingProcessCpuTimes(tgid); + } - for (int i = 0; i < threadCount; i++) { - pid_t tid; - if (android::base::ParseInt<pid_t>(dirlist[i]->d_name, &tid)) { - outThreadIds.push_back(tid); - } - free(dirlist[i]); + bool startAggregatingTaskCpuTimes(pid_t pid, uint16_t aggregationKey) { + return android::bpf::startAggregatingTaskCpuTimes(pid, aggregationKey); } - free(dirlist); - return true; -} + std::optional<std::unordered_map<uint16_t, std::vector<std::vector<uint64_t>>>> + getAggregatedTaskCpuFreqTimes(pid_t pid, const std::vector<uint16_t> &aggregationKeys) { + return android::bpf::getAggregatedTaskCpuFreqTimes(pid, aggregationKeys); + } +}; -// Reads contents of a time_in_state file and returns times as a vector of times per frequency -// A time_in_state file contains pairs of frequency - time (in jiffies): -// -// cpu0 -// 300000 30 -// 403200 0 -// cpu4 -// 710400 10 -// 825600 20 -// 940800 30 -// -static bool getThreadTimeInState(const std::string &procPath, const pid_t pid, const pid_t tid, - const size_t frequencyCount, - std::vector<uint64_t> &outThreadTimeInState) { - std::string timeInStateFilePath = - android::base::StringPrintf("%s/%u/task/%u/time_in_state", procPath.c_str(), pid, tid); - std::string data; - - if (!android::base::ReadFileToString(timeInStateFilePath, &data)) { - ALOGE("Cannot read file: %s", timeInStateFilePath.c_str()); - return false; +// ICpuTimeInStateReader that uses JNI to provide a map of aggregated CPU time-in-state +// values. +// This version of CpuTimeInStateReader is used exclusively for providing mock data in tests. +class MockCpuTimeInStateReader : public ICpuTimeInStateReader { +private: + JNIEnv *mEnv; + jobject mCpuTimeInStateReader; + +public: + MockCpuTimeInStateReader(JNIEnv *env, jobject cpuTimeInStateReader) + : mEnv(env), mCpuTimeInStateReader(cpuTimeInStateReader) {} + + size_t getCpuFrequencyCount(); + + bool startTrackingProcessCpuTimes(pid_t tgid); + + bool startAggregatingTaskCpuTimes(pid_t pid, uint16_t aggregationKey); + + std::optional<std::unordered_map<uint16_t, std::vector<std::vector<uint64_t>>>> + getAggregatedTaskCpuFreqTimes(pid_t tgid, const std::vector<uint16_t> &aggregationKeys); +}; + +static ICpuTimeInStateReader *getCpuTimeInStateReader(JNIEnv *env, + jobject cpuTimeInStateReaderObject) { + if (cpuTimeInStateReaderObject) { + return new MockCpuTimeInStateReader(env, cpuTimeInStateReaderObject); + } else { + return new BpfCpuTimeInStateReader(); } +} - auto lines = android::base::Split(data, "\n"); - size_t index = 0; - for (const auto &line : lines) { - if (line.empty()) { - continue; - } +static jint getCpuFrequencyCount(JNIEnv *env, jclass, jobject cpuTimeInStateReaderObject) { + std::unique_ptr<ICpuTimeInStateReader> cpuTimeInStateReader( + getCpuTimeInStateReader(env, cpuTimeInStateReaderObject)); + return cpuTimeInStateReader->getCpuFrequencyCount(); +} - auto numbers = android::base::Split(line, " "); - if (numbers.size() != 2) { - continue; - } - uint64_t timeInState; - if (!android::base::ParseUint<uint64_t>(numbers[1], &timeInState)) { - ALOGE("Invalid time_in_state file format: %s", timeInStateFilePath.c_str()); +static jboolean startTrackingProcessCpuTimes(JNIEnv *env, jclass, jint tgid, + jobject cpuTimeInStateReaderObject) { + std::unique_ptr<ICpuTimeInStateReader> cpuTimeInStateReader( + getCpuTimeInStateReader(env, cpuTimeInStateReaderObject)); + return cpuTimeInStateReader->startTrackingProcessCpuTimes(tgid); +} + +static jboolean startAggregatingThreadCpuTimes(JNIEnv *env, jclass, jintArray selectedThreadIdArray, + jobject cpuTimeInStateReaderObject) { + ScopedIntArrayRO selectedThreadIds(env, selectedThreadIdArray); + std::unique_ptr<ICpuTimeInStateReader> cpuTimeInStateReader( + getCpuTimeInStateReader(env, cpuTimeInStateReaderObject)); + + for (int i = 0; i < selectedThreadIds.size(); i++) { + if (!cpuTimeInStateReader->startAggregatingTaskCpuTimes(selectedThreadIds[i], + SELECTED_THREAD_AGGREGATION_KEY)) { return false; } - if (index < frequencyCount) { - outThreadTimeInState[index] = timeInState; - } - index++; } + return true; +} +// Converts time-in-state data from a vector of vectors to a flat array. +// Also converts from nanoseconds to milliseconds. +static bool flattenTimeInStateData(ScopedLongArrayRW &cpuTimesMillis, + const std::vector<std::vector<uint64_t>> &data) { + size_t frequencyCount = cpuTimesMillis.size(); + size_t index = 0; + for (const auto &cluster : data) { + for (const uint64_t &timeNanos : cluster) { + if (index < frequencyCount) { + cpuTimesMillis[index] = timeNanos / NSEC_PER_MSEC; + } + index++; + } + } if (index != frequencyCount) { - ALOGE("Incorrect number of frequencies %u in %s. Expected %u", - (uint32_t)outThreadTimeInState.size(), timeInStateFilePath.c_str(), - (uint32_t)frequencyCount); + ALOGE("CPU time-in-state reader returned data for %zu frequencies; expected: %zu", index, + frequencyCount); return false; } return true; } -static int pidCompare(const void *a, const void *b) { - return (*(pid_t *)a - *(pid_t *)b); -} - -static inline bool isSelectedThread(const pid_t tid, const pid_t *selectedThreadIds, - const size_t selectedThreadCount) { - return bsearch(&tid, selectedThreadIds, selectedThreadCount, sizeof(pid_t), pidCompare) != NULL; -} - -// Reads all /proc/<pid>/task/*/time_in_state files and aggregates per-frequency +// Reads all CPU time-in-state data accumulated by BPF and aggregates per-frequency // time in state data for all threads. Also, separately aggregates time in state for // selected threads whose TIDs are passes as selectedThreadIds. -static void aggregateThreadCpuTimes(const std::string &procPath, const pid_t pid, - const std::vector<pid_t> &threadIds, - const size_t frequencyCount, const pid_t *selectedThreadIds, - const size_t selectedThreadCount, - uint64_t *threadCpuTimesMillis, - uint64_t *selectedThreadCpuTimesMillis) { - for (size_t j = 0; j < frequencyCount; j++) { - threadCpuTimesMillis[j] = 0; - selectedThreadCpuTimesMillis[j] = 0; - } +static jboolean readProcessCpuUsage(JNIEnv *env, jclass, jint pid, + jlongArray threadCpuTimesMillisArray, + jlongArray selectedThreadCpuTimesMillisArray, + jobject cpuTimeInStateReaderObject) { + ScopedLongArrayRW threadCpuTimesMillis(env, threadCpuTimesMillisArray); + ScopedLongArrayRW selectedThreadCpuTimesMillis(env, selectedThreadCpuTimesMillisArray); + std::unique_ptr<ICpuTimeInStateReader> cpuTimeInStateReader( + getCpuTimeInStateReader(env, cpuTimeInStateReaderObject)); - for (size_t i = 0; i < threadIds.size(); i++) { - pid_t tid = threadIds[i]; - std::vector<uint64_t> timeInState(frequencyCount); - if (!getThreadTimeInState(procPath, pid, tid, frequencyCount, timeInState)) { - continue; - } + const size_t frequencyCount = cpuTimeInStateReader->getCpuFrequencyCount(); - bool selectedThread = isSelectedThread(tid, selectedThreadIds, selectedThreadCount); - for (size_t j = 0; j < frequencyCount; j++) { - threadCpuTimesMillis[j] += timeInState[j]; - if (selectedThread) { - selectedThreadCpuTimesMillis[j] += timeInState[j]; - } - } + if (threadCpuTimesMillis.size() != frequencyCount) { + ALOGE("Invalid threadCpuTimesMillis array length: %zu frequencies; expected: %zu", + threadCpuTimesMillis.size(), frequencyCount); + return false; } + + if (selectedThreadCpuTimesMillis.size() != frequencyCount) { + ALOGE("Invalid selectedThreadCpuTimesMillis array length: %zu frequencies; expected: %zu", + selectedThreadCpuTimesMillis.size(), frequencyCount); + return false; + } + for (size_t i = 0; i < frequencyCount; i++) { - threadCpuTimesMillis[i] *= gJiffyMillis; - selectedThreadCpuTimesMillis[i] *= gJiffyMillis; + threadCpuTimesMillis[i] = 0; + selectedThreadCpuTimesMillis[i] = 0; } -} -// Reads process utime and stime from the /proc/<pid>/stat file. -// Format of this file is described in https://man7.org/linux/man-pages/man5/proc.5.html. -static bool getProcessCpuTime(const std::string &procPath, const pid_t pid, - uint64_t &outTimeMillis) { - std::string statFilePath = android::base::StringPrintf("%s/%u/stat", procPath.c_str(), pid); - std::string data; - if (!android::base::ReadFileToString(statFilePath, &data)) { + std::optional<std::unordered_map<uint16_t, std::vector<std::vector<uint64_t>>>> data = + cpuTimeInStateReader->getAggregatedTaskCpuFreqTimes(pid, + {DEFAULT_THREAD_AGGREGATION_KEY, + SELECTED_THREAD_AGGREGATION_KEY}); + if (!data) { + ALOGE("Cannot read thread CPU times for PID %d", pid); return false; } - auto fields = android::base::Split(data, " "); - uint64_t utime, stime; - - // Field 14 (counting from 1) is utime - process time in user space, in jiffies - // Field 15 (counting from 1) is stime - process time in system space, in jiffies - if (fields.size() < 15 || !android::base::ParseUint(fields[13], &utime) || - !android::base::ParseUint(fields[14], &stime)) { - ALOGE("Invalid file format %s", statFilePath.c_str()); + if (!flattenTimeInStateData(threadCpuTimesMillis, (*data)[DEFAULT_THREAD_AGGREGATION_KEY])) { return false; } - outTimeMillis = (utime + stime) * gJiffyMillis; - return true; -} + if (!flattenTimeInStateData(selectedThreadCpuTimesMillis, + (*data)[SELECTED_THREAD_AGGREGATION_KEY])) { + return false; + } -// Estimates per cluster per frequency CPU time for the entire process -// by distributing the total process CPU time proportionately to how much -// CPU time its threads took on those clusters/frequencies. This algorithm -// works more accurately when when we have equally distributed concurrency. -// TODO(b/169279846): obtain actual process CPU times from the kernel -static void estimateProcessTimeInState(const uint64_t processCpuTimeMillis, - const uint64_t *threadCpuTimesMillis, - const size_t frequencyCount, - uint64_t *processCpuTimesMillis) { - uint64_t totalCpuTimeAllThreads = 0; + // threadCpuTimesMillis returns CPU times for _all_ threads, including the selected ones for (size_t i = 0; i < frequencyCount; i++) { - totalCpuTimeAllThreads += threadCpuTimesMillis[i]; + threadCpuTimesMillis[i] += selectedThreadCpuTimesMillis[i]; } - if (totalCpuTimeAllThreads != 0) { - for (size_t i = 0; i < frequencyCount; i++) { - processCpuTimesMillis[i] = - processCpuTimeMillis * threadCpuTimesMillis[i] / totalCpuTimeAllThreads; - } - } else { - for (size_t i = 0; i < frequencyCount; i++) { - processCpuTimesMillis[i] = 0; - } - } + return true; } -static jboolean readProcessCpuUsage(JNIEnv *env, jclass, jstring procPath, jint pid, - jintArray selectedThreadIdArray, - jlongArray processCpuTimesMillisArray, - jlongArray threadCpuTimesMillisArray, - jlongArray selectedThreadCpuTimesMillisArray) { - ScopedUtfChars procPathChars(env, procPath); - ScopedIntArrayRO selectedThreadIds(env, selectedThreadIdArray); - ScopedLongArrayRW processCpuTimesMillis(env, processCpuTimesMillisArray); - ScopedLongArrayRW threadCpuTimesMillis(env, threadCpuTimesMillisArray); - ScopedLongArrayRW selectedThreadCpuTimesMillis(env, selectedThreadCpuTimesMillisArray); +static const JNINativeMethod g_single_methods[] = { + {"getCpuFrequencyCount", + "(Lcom/android/internal/os/KernelSingleProcessCpuThreadReader$CpuTimeInStateReader;)I", + (void *)getCpuFrequencyCount}, + {"startTrackingProcessCpuTimes", + "(ILcom/android/internal/os/KernelSingleProcessCpuThreadReader$CpuTimeInStateReader;)Z", + (void *)startTrackingProcessCpuTimes}, + {"startAggregatingThreadCpuTimes", + "([ILcom/android/internal/os/KernelSingleProcessCpuThreadReader$CpuTimeInStateReader;)Z", + (void *)startAggregatingThreadCpuTimes}, + {"readProcessCpuUsage", + "(I[J[J" + "Lcom/android/internal/os/KernelSingleProcessCpuThreadReader$CpuTimeInStateReader;)Z", + (void *)readProcessCpuUsage}, +}; - std::string procPathStr(procPathChars.c_str()); +int register_com_android_internal_os_KernelSingleProcessCpuThreadReader(JNIEnv *env) { + return RegisterMethodsOrDie(env, "com/android/internal/os/KernelSingleProcessCpuThreadReader", + g_single_methods, NELEM(g_single_methods)); +} - // Get all thread IDs for the process. - std::vector<pid_t> threadIds; - if (!getThreadIds(procPathStr, pid, threadIds)) { - ALOGE("Could not obtain thread IDs from: %s", procPathStr.c_str()); +size_t MockCpuTimeInStateReader::getCpuFrequencyCount() { + jclass cls = mEnv->GetObjectClass(mCpuTimeInStateReader); + jmethodID mid = mEnv->GetMethodID(cls, "getCpuFrequencyCount", "()I"); + if (mid == 0) { + ALOGE("Couldn't find the method getCpuFrequencyCount"); return false; } + return (size_t)mEnv->CallIntMethod(mCpuTimeInStateReader, mid); +} - size_t frequencyCount = processCpuTimesMillis.size(); - - if (threadCpuTimesMillis.size() != frequencyCount) { - ALOGE("Invalid array length: threadCpuTimesMillis"); +bool MockCpuTimeInStateReader::startTrackingProcessCpuTimes(pid_t tgid) { + jclass cls = mEnv->GetObjectClass(mCpuTimeInStateReader); + jmethodID mid = mEnv->GetMethodID(cls, "startTrackingProcessCpuTimes", "(I)Z"); + if (mid == 0) { + ALOGE("Couldn't find the method startTrackingProcessCpuTimes"); return false; } - if (selectedThreadCpuTimesMillis.size() != frequencyCount) { - ALOGE("Invalid array length: selectedThreadCpuTimesMillisArray"); + return mEnv->CallBooleanMethod(mCpuTimeInStateReader, mid, tgid); +} + +bool MockCpuTimeInStateReader::startAggregatingTaskCpuTimes(pid_t pid, uint16_t aggregationKey) { + jclass cls = mEnv->GetObjectClass(mCpuTimeInStateReader); + jmethodID mid = mEnv->GetMethodID(cls, "startAggregatingTaskCpuTimes", "(II)Z"); + if (mid == 0) { + ALOGE("Couldn't find the method startAggregatingTaskCpuTimes"); return false; } + return mEnv->CallBooleanMethod(mCpuTimeInStateReader, mid, pid, aggregationKey); +} - aggregateThreadCpuTimes(procPathStr, pid, threadIds, frequencyCount, selectedThreadIds.get(), - selectedThreadIds.size(), - reinterpret_cast<uint64_t *>(threadCpuTimesMillis.get()), - reinterpret_cast<uint64_t *>(selectedThreadCpuTimesMillis.get())); - - uint64_t processCpuTime; - bool ret = getProcessCpuTime(procPathStr, pid, processCpuTime); - if (ret) { - estimateProcessTimeInState(processCpuTime, - reinterpret_cast<uint64_t *>(threadCpuTimesMillis.get()), - frequencyCount, - reinterpret_cast<uint64_t *>(processCpuTimesMillis.get())); +std::optional<std::unordered_map<uint16_t, std::vector<std::vector<uint64_t>>>> +MockCpuTimeInStateReader::getAggregatedTaskCpuFreqTimes( + pid_t pid, const std::vector<uint16_t> &aggregationKeys) { + jclass cls = mEnv->GetObjectClass(mCpuTimeInStateReader); + jmethodID mid = + mEnv->GetMethodID(cls, "getAggregatedTaskCpuFreqTimes", "(I)[Ljava/lang/String;"); + if (mid == 0) { + ALOGE("Couldn't find the method getAggregatedTaskCpuFreqTimes"); + return {}; } - return ret; -} -static const JNINativeMethod g_single_methods[] = { - {"readProcessCpuUsage", "(Ljava/lang/String;I[I[J[J[J)Z", (void *)readProcessCpuUsage}, -}; + std::unordered_map<uint16_t, std::vector<std::vector<uint64_t>>> map; -int register_com_android_internal_os_KernelSingleProcessCpuThreadReader(JNIEnv *env) { - return RegisterMethodsOrDie(env, "com/android/internal/os/KernelSingleProcessCpuThreadReader", - g_single_methods, NELEM(g_single_methods)); + jobjectArray stringArray = + (jobjectArray)mEnv->CallObjectMethod(mCpuTimeInStateReader, mid, pid); + int size = mEnv->GetArrayLength(stringArray); + for (int i = 0; i < size; i++) { + ScopedUtfChars line(mEnv, (jstring)mEnv->GetObjectArrayElement(stringArray, i)); + uint16_t aggregationKey; + std::vector<std::vector<uint64_t>> times; + + // Each string is formatted like this: "aggKey:t0_0 t0_1...:t1_0 t1_1..." + auto fields = android::base::Split(line.c_str(), ":"); + android::base::ParseUint(fields[0], &aggregationKey); + + for (int j = 1; j < fields.size(); j++) { + auto numbers = android::base::Split(fields[j], " "); + + std::vector<uint64_t> chunk; + for (int k = 0; k < numbers.size(); k++) { + uint64_t time; + android::base::ParseUint(numbers[k], &time); + chunk.emplace_back(time); + } + times.emplace_back(chunk); + } + + map.emplace(aggregationKey, times); + } + + return map; } } // namespace android diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 1250eb776176..bd8c73435de3 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1361,7 +1361,7 @@ android:description="@string/permdesc_systemCamera" android:protectionLevel="system|signature" /> - <!-- Allows receiving the camera service notifications when a camera is opened + <!-- @SystemApi Allows receiving the camera service notifications when a camera is opened (by a certain application package) or closed. @hide --> <permission android:name="android.permission.CAMERA_OPEN_CLOSE_LISTENER" @@ -2212,6 +2212,13 @@ <permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" android:protectionLevel="signature|privileged" /> + <!-- Allows to read device identifiers and use ICC based authentication like EAP-AKA. + Often required in authentication to access the carrier's server and manage services + of the subscriber. + <p>Protection level: signature|appop --> + <permission android:name="android.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER" + android:protectionLevel="signature|appop" /> + <!-- @SystemApi Allows read access to emergency number information for ongoing calls or SMS sessions. @hide Used internally. --> @@ -2379,6 +2386,15 @@ <permission android:name="android.permission.READ_CARRIER_APP_INFO" android:protectionLevel="signature" /> + <!-- Must be required by an GbaService to ensure that only the + system can bind to it. + <p>Protection level: signature + @SystemApi + @hide + --> + <permission android:name="android.permission.BIND_GBA_SERVICE" + android:protectionLevel="signature" /> + <!-- ================================== --> <!-- Permissions for sdcard interaction --> <!-- ================================== --> @@ -3953,6 +3969,14 @@ <permission android:name="android.permission.ACCESS_SURFACE_FLINGER" android:protectionLevel="signature" /> + <!-- @SystemApi Allows an application to rotate a surface by arbitrary degree. + This is a sub-feature of ACCESS_SURFACE_FLINGER and can be granted in a more concrete way. + <p>Not for use by third-party applications. + @hide + --> + <permission android:name="android.permission.ROTATE_SURFACE_FLINGER" + android:protectionLevel="signature|recents" /> + <!-- Allows an application to take screen shots and more generally get access to the frame buffer data. <p>Not for use by third-party applications. @@ -4615,7 +4639,7 @@ <!-- Allows access to keyguard secure storage. Only allowed for system processes. @hide --> <permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" - android:protectionLevel="signature" /> + android:protectionLevel="signature|setup" /> <!-- Allows applications to set the initial lockscreen state. <p>Not for use by third-party applications. @hide --> diff --git a/core/res/OWNERS b/core/res/OWNERS new file mode 100644 index 000000000000..263d638353d6 --- /dev/null +++ b/core/res/OWNERS @@ -0,0 +1,17 @@ +adamp@google.com +alanv@google.com +dsandler@android.com +dsandler@google.com +hackbod@android.com +hackbod@google.com +jsharkey@android.com +jsharkey@google.com +michaelwr@google.com +nandana@google.com +narayan@google.com +ogunwale@google.com +patb@google.com +svetoslavganov@android.com +svetoslavganov@google.com +toddke@google.com +yamasani@google.com diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 171d89628518..d41acda8bf3b 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-diens"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensorkennisgewingdiens"</string> <string name="twilight_service" msgid="8964898045693187224">"Skemerdiens"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tydsonebespeurder (geen konnektiwiteit nie)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Jou toestel sal uitgevee word"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Die administrasieprogram kan nie gebruik word nie. Jou toestel sal nou uitgevee word.\n\nKontak jou organisasie se administrateur as jy vrae het."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Druk is gedeaktiveer deur <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-verbinding"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Program loop tans"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programme wat batterykrag gebruik"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Vergroting"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruik tans batterykrag"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> programme gebruik tans batterykrag"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tik vir besonderhede oor battery- en datagebruik"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nuut: Venstervergrootglas"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Jy kan nou jou hele skerm of \'n deel daarvan vergroot"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Skakel aan in Instellings"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Maak toe"</string> </resources> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 5871fe24920a..fe45f9e4ae71 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS አገልግሎት"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"የዳሳሽ ማሳወቂያ አገልግሎት"</string> <string name="twilight_service" msgid="8964898045693187224">"የውጋገን አገልግሎት"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"የሰዓት ሰቅ አንባቢ (ግንኙነት የለም)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"የእርስዎ መሣሪያ ይደመሰሳል"</string> <string name="factory_reset_message" msgid="2657049595153992213">"የአስተዳዳሪ መተግበሪያ ስራ ላይ ሊውል አይችልም። የእርስዎን መሣሪያ አሁን ይደመሰሳል።\n\nጥያቄዎች ካለዎት የድርጅትዎን አስተዳዳሪ ያነጋግሩ።"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"ማተም በ<xliff:g id="OWNER_APP">%s</xliff:g> ተሰናክሏል።"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"የዩኤስቢ ግንኙነት"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"APP እየሠራ ነው"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ባትሪ በመፍጀት ላይ ያሉ መተግበሪያዎች"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ማጉላት"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ባትሪ እየተጠቀመ ነው"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> መተግበሪያዎች ባትሪ እየተጠቀሙ ነው"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"በባትሪ እና ውሂብ አጠቃቀም ላይ ዝርዝሮችን ለማግኘት መታ ያድርጉ"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"አዲስ፦ የመስኮት ማጉያ"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"አሁን የተወሰነ ወይም ሁሉንም ማያ ገጽዎን ማጉላት ይችላሉ"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"በቅንብሮች ውስጥ ያብሩ"</string> + <string name="dismiss_action" msgid="1728820550388704784">"አሰናብት"</string> </resources> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index b57876906a94..89c4fea5996b 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -207,6 +207,7 @@ <string name="gnss_service" msgid="8907781262179951385">"خدمة GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"خدمة إشعارات جهاز الاستشعار"</string> <string name="twilight_service" msgid="8964898045693187224">"خدمة الغسق"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"أداة التعرّف على المنطقة الزمنية (ليس هناك حاجة للاتصال بالشبكة)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"سيتم محو بيانات جهازك."</string> <string name="factory_reset_message" msgid="2657049595153992213">"تعذّر استخدام تطبيق المشرف. سيتم محو بيانات جهازك الآن.\n\nإذا كانت لديك أسئلة، اتصل بمشرف مؤسستك."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"تم إيقاف الطباعة بواسطة <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -299,8 +300,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"اتصال USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"التطبيق قيد التشغيل"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"التطبيقات التي تستهلك البطارية"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"التكبير"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"يستخدم تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> البطارية"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"تستخدم <xliff:g id="NUMBER">%1$d</xliff:g> من التطبيقات البطارية"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"انقر للحصول على تفاصيل حول البطارية واستخدام البيانات"</string> @@ -2326,12 +2326,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"جديد: Window Magnifier"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"يمكنك الآن تكبير الشاشة كلها أو جزء منها."</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"التفعيل من خلال \"الإعدادات\""</string> + <string name="dismiss_action" msgid="1728820550388704784">"إغلاق"</string> </resources> diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index f1b0d84883a0..7dac9a2991ec 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS সেৱা"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"ছেন্সৰ জাননী সেৱা"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight সেৱা"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"সময় মণ্ডল চিনাক্তকাৰী (সংযোগ নাই)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"আপোনাৰ ডিভাইচৰ ডেটা মচা হ\'ব"</string> <string name="factory_reset_message" msgid="2657049595153992213">"এই প্ৰশাসক এপটো ব্যৱহাৰ কৰিব নোৱাৰি। এতিয়া আপোনাৰ ডিভাইচটোৰ ডেটা মচা হ\'ব।\n\nআপোনাৰ কিবা প্ৰশ্ন থাকিলে আপোনাৰ প্ৰতিষ্ঠানৰ প্ৰশাসকৰ সৈতে যোগাযোগ কৰক।"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"প্ৰিণ্ট কৰা কাৰ্য <xliff:g id="OWNER_APP">%s</xliff:g>এ অক্ষম কৰি ৰাখিছে।"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"ইউএছবি সংযোগ"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"এপ্ চলি আছে"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"বেটাৰি খৰচ কৰা এপসমূহ"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"বিবৰ্ধন"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ বেটাৰি ব্যৱহাৰ কৰি আছে"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>টা এপে বেটাৰি ব্যৱহাৰ কৰি আছে"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"বেটাৰি আৰু ডেটাৰ ব্যৱহাৰৰ বিষয়ে বিশদভাৱে জানিবলৈ টিপক"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"নতুন: ৱিণ্ড’ বিৱৰ্ধক"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"আপুনি সকলো অথবা কেইখনমান স্ক্ৰীন বিবৰ্ধন কৰিব পাৰে"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ছেটিঙত অন কৰক"</string> + <string name="dismiss_action" msgid="1728820550388704784">"অগ্ৰাহ্য কৰক"</string> </resources> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index 01fb48e18462..9fdc7542ac49 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS Xidməti"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Bildiriş Xidməti"</string> <string name="twilight_service" msgid="8964898045693187224">"Alaqaranlıq Xidməti"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Saat Qurşağı Aşkarlayıcısı (Bağlantı yoxdur)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Cihazınız təmizlənəcəkdir"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Admin tətbiqini istifadə etmək mümkün deyil. Cihaz indi təmizlənəcək.\n\nSualınız varsa, təşkilatın admini ilə əlaqə saxlayın."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Çap <xliff:g id="OWNER_APP">%s</xliff:g> tərəfindən deaktiv edildi."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB əlaqə"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Tətbiq işləyir"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Batareyadan istifadə edən tətbiqlər"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Böyütmə"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> batareyadan istifadə edir"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> tətbiq batareyadan istifadə edir"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Batareya və data istifadəsi haqqında ətraflı məlumat üçün klikləyin"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Yeni: Pəncərə Böyüdücüsü"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"İndi ekranı qismən və ya tam şəkildə böyüdə bilərsiniz"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ayarlarda aktiv edin"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Qapadın"</string> </resources> diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index bfbd3e4586f2..3be770c89ca9 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -201,6 +201,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS usluga"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Usluga obaveštenja senzora"</string> <string name="twilight_service" msgid="8964898045693187224">"Usluga Sumrak"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detektor vremenske zone (nema internet veze)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Uređaj će biti obrisan"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Ne možete da koristite ovu aplikaciju za administratore. Uređaj će sada biti obrisan.\n\nAko imate pitanja, kontaktirajte administratora organizacije."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Štampanje je onemogućila aplikacija <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -290,8 +291,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB veza"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aktivna aplikacija"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije koje troše bateriju"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Uvećanje"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> koristi bateriju"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikacije (<xliff:g id="NUMBER">%1$d</xliff:g>) koriste bateriju"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite za detalje o bateriji i potrošnji podataka"</string> @@ -932,7 +932,7 @@ <string name="granularity_label_link" msgid="9007852307112046526">"link"</string> <string name="granularity_label_line" msgid="376204904280620221">"red"</string> <string name="factorytest_failed" msgid="3190979160945298006">"Fabričko testiranje nije uspelo"</string> - <string name="factorytest_not_system" msgid="5658160199925519869">"Radnja FACTORY_TEST je podržana samo za pakete instalirane u direktorijumu /system/app."</string> + <string name="factorytest_not_system" msgid="5658160199925519869">"Radnja FACTORY_TEST je podržana samo za pakete instalirane u folderu /system/app."</string> <string name="factorytest_no_action" msgid="339252838115675515">"Nije pronađen nijedan paket koji obezbeđuje radnju FACTORY_TEST."</string> <string name="factorytest_reboot" msgid="2050147445567257365">"Restartuj"</string> <string name="js_dialog_title" msgid="7464775045615023241">"Na stranici na adresi „<xliff:g id="TITLE">%s</xliff:g>“ piše:"</string> @@ -2048,7 +2048,7 @@ <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Baterija telefona je dovoljno napunjena. Funkcije više nisu ograničene."</string> <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Baterija tableta je dovoljno napunjena. Funkcije više nisu ograničene."</string> <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Baterija uređaja je dovoljno napunjena. Funkcije više nisu ograničene."</string> - <string name="mime_type_folder" msgid="2203536499348787650">"Direktorijum"</string> + <string name="mime_type_folder" msgid="2203536499348787650">"Folder"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android aplikacija"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Datoteka"</string> <string name="mime_type_generic_ext" msgid="9220220924380909486">"<xliff:g id="EXTENSION">%1$s</xliff:g> datoteka"</string> @@ -2224,12 +2224,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novo: Lupa za prozor"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Možete da uvećate deo ekrana ili ceo ekran"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Uključite u Podešavanjima"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Odbaci"</string> </resources> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index c4a3a7e980c4..fc2849e55f57 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Служба GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Служба апавяшчэнняў датчыка"</string> <string name="twilight_service" msgid="8964898045693187224">"Служба Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Дэтэктар часавога пояса (няма падключэння)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Даныя вашай прылады будуць сцерты"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Немагчыма выкарыстоўваць праграму адміністравання. Звесткі на вашай прыладзе будуць выдалены.\n\nКалі ў вас ёсць пытанні, звярніцеся да адміністратара арганізацыі."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Друк адключаны ўладальнікам праграмы <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Падключэнне USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Праграма працуе"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Праграмы, якія выкарыстоўваюць акумулятар"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Павелічэнне"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> выкарыстоўвае акумулятар"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Наступная колькасць праграм выкарыстоўваюць акумулятар: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Дакраніцеся, каб даведацца пра выкарыстанне трафіка і акумулятара"</string> @@ -2258,12 +2258,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Новая функцыя Window Magnifier"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Цяпер можна павялічваць увесь экран ці яго частку."</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Уключыць у Наладах"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Адхіліць"</string> </resources> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 07f1ce7b9bf9..a6321f5253b4 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Услуга за GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Услуга за известия за сензорите"</string> <string name="twilight_service" msgid="8964898045693187224">"Услуга Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Инструмент за установяване на часовата зона (няма връзка)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Данните на устройството ви ще бъдат изтрити"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Приложението за администриране не може да се използва. Сега данните на устройството ви ще бъдат изтрити.\n\nАко имате въпроси, свържете се с администратора на организацията си."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Отпечатването е деактивиранo от <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB връзка"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Приложението работи"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Приложения, използващи батерията"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Увеличение"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> използва батерията"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> приложения използват батерията"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Докоснете за информация относно използването на батерията и преноса на данни"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Ново: Увеличаване на прозорци"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Можете да увеличите целия екран или част от него"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Включете от настройките"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Отхвърляне"</string> </resources> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index 9b85fc7a4d7d..269d2c714595 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS পরিষেবা"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"সেন্সর বিজ্ঞপ্তি পরিষেবা"</string> <string name="twilight_service" msgid="8964898045693187224">"গোধূলি পরিষেবা"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"টাইম জোন ডিটেক্টর (কানেকশন নেই)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"আপনার ডিভাইসটি মুছে ফেলা হবে"</string> <string name="factory_reset_message" msgid="2657049595153992213">"অ্যাডমিন অ্যাপটি ব্যবহার করা যাবে না। আপনার ডিভাইসে থাকা সবকিছু এখন মুছে ফেলা হবে।\n\nকোনও প্রশ্ন থাকলে আপনার প্রতিষ্ঠানের অ্যাডমিনের সাথে যোগাযোগ করুন।"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> প্রিন্টিং বন্ধ রেখেছে।"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB সংযোগ"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"অ্যাপ চলছে"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"কিছু অ্যাপ ব্যাটারি ব্যবহার করছে"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"বড় করে দেখুন"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপটি ব্যাটারি ব্যবহার করছে"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>টি অ্যাপ ব্যাটারি ব্যবহার করছে"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ব্যাটারি এবং ডেটার ব্যবহারের বিশদ বিবরণের জন্য ট্যাপ করুন"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"নতুন: উইন্ডো ম্যাগনিফায়ার"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"এখন আপনি কিছু বা সবকটি স্ক্রিন বড় করে দেখতে পারেন"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"সেটিংস থেকে চালু করুন"</string> + <string name="dismiss_action" msgid="1728820550388704784">"বাতিল করুন"</string> </resources> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index 3d2249b17122..6ecad70d01a1 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -201,6 +201,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Usluga GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Usluga obavještavanja putem senzora"</string> <string name="twilight_service" msgid="8964898045693187224">"Usluga Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detektor vremenske zone (nije povezan)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Uređaj će biti izbrisan"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Nije moguće koristiti aplikaciju administratora. Potpuno će se izbrisati podaci na vašem uređaju.\n\nAko imate pitanja, obratite se administratoru svoje organizacije."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Štampanje je onemogućila aplikacija <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -290,8 +291,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB veza"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Pokrenuta aplikacija"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije koje troše bateriju"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Uvećavanje"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> troši bateriju"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Broj aplikacija koje troše bateriju: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite za detalje o potrošnji baterije i prijenosa podataka"</string> @@ -2224,12 +2224,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novo: povećalo prozora"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Sada možete uvećati dio ekrana ili cijeli ekran"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Uključite u Postavkama"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Odbaci"</string> </resources> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index f1845e340afa..c72ca7412ef1 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Servei GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Servei de notificacions de sensor"</string> <string name="twilight_service" msgid="8964898045693187224">"Servei Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de zona horària (sense connectivitat)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"El contingut del dispositiu s\'esborrarà"</string> <string name="factory_reset_message" msgid="2657049595153992213">"No es pot utilitzar l\'aplicació d\'administració. S\'esborraran les dades del dispositiu.\n\nSi tens cap dubte, contacta amb l\'administrador de la teva organització."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ha desactivat la impressió."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Connexió USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplicació en execució"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicacions que consumeixen bateria"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliació"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> està consumint bateria"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicacions estan consumint bateria"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca per obtenir informació sobre l\'ús de dades i de bateria"</string> @@ -1800,8 +1800,8 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"Actualitzat per l\'administrador"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"Suprimit per l\'administrador"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"D\'acord"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Per allargar la durada de la bateria, la funció Estalvi de bateria fa el següent:\n\n• Activa el tema fosc.\n• Desactiva o restringeix l\'activitat en segon pla, alguns efectes visuals i altres funcions com \"Ok Google\".\n\n"<annotation id="url">"Més informació"</annotation></string> - <string name="battery_saver_description" msgid="6794188153647295212">"Per allargar la durada de la bateria, la funció Estalvi de bateria fa el següent:\n\n• Activa el tema fosc.\n• Desactiva o restringeix l\'activitat en segon pla, alguns efectes visuals i altres funcions com \"Ok Google\"."</string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Per allargar la durada de la bateria, la funció Estalvi de bateria:\n\n• Activa el tema fosc.\n• Desactiva o restringeix l\'activitat en segon pla, alguns efectes visuals i altres funcions com \"Ok Google\".\n\n"<annotation id="url">"Més informació"</annotation></string> + <string name="battery_saver_description" msgid="6794188153647295212">"Per allargar la durada de la bateria, la funció Estalvi de bateria:\n\n• Activa el tema fosc.\n• Desactiva o restringeix l\'activitat en segon pla, alguns efectes visuals i altres funcions com \"Ok Google\"."</string> <string name="data_saver_description" msgid="4995164271550590517">"Per reduir l\'ús de dades, la funció Economitzador de dades evita que determinades aplicacions enviïn o rebin dades en segon pla. L\'aplicació que estiguis fent servir podrà accedir a les dades, però menys sovint. Això vol dir, per exemple, que les imatges no es mostraran fins que no les toquis."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Activar l\'Economitzador de dades?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Activa"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novetat: Window Magnifier"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Ara pots ampliar la pantalla completa o una part"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activa a Configuració"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Ignora"</string> </resources> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 42d56369c3af..8174a6e17c60 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Služba GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Služba oznámení ze senzoru"</string> <string name="twilight_service" msgid="8964898045693187224">"Služba detekce soumraku"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detektor časového pásma (bez připojení)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Zařízení bude vymazáno"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Aplikaci pro správu nelze použít. Zařízení teď bude vymazáno.\n\nV případě dotazů vám pomůže administrátor organizace."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Aplikace <xliff:g id="OWNER_APP">%s</xliff:g> tisk zakazuje."</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Připojení USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikace je spuštěna"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikace spotřebovávají baterii"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Zvětšení"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> využívá baterii"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikace (<xliff:g id="NUMBER">%1$d</xliff:g>) využívají baterii"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Klepnutím zobrazíte podrobnosti o využití baterie a dat"</string> @@ -1282,7 +1282,7 @@ <string name="volume_icon_description_notification" msgid="579091344110747279">"Hlasitost oznámení"</string> <string name="ringtone_default" msgid="9118299121288174597">"Výchozí vyzvánění"</string> <string name="ringtone_default_with_actual" msgid="2709686194556159773">"Výchozí (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string> - <string name="ringtone_silent" msgid="397111123930141876">"Žádný"</string> + <string name="ringtone_silent" msgid="397111123930141876">"Žádné"</string> <string name="ringtone_picker_title" msgid="667342618626068253">"Vyzvánění"</string> <string name="ringtone_picker_title_alarm" msgid="7438934548339024767">"Zvuky budíku"</string> <string name="ringtone_picker_title_notification" msgid="6387191794719608122">"Zvuky upozornění"</string> @@ -2258,12 +2258,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novinka: Zvětšení oken"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Nyní můžete zvětšit celou obrazovku nebo její část"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Zapnout v Nastavení"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Zavřít"</string> </resources> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 0487406d4e7c..0bd965775700 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-tjeneste"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Tjenesten Sensor Notification"</string> <string name="twilight_service" msgid="8964898045693187224">"Tjenesten Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tidszoneregistrering (ingen forbindelse)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Enheden slettes"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Administrationsappen kan ikke bruges. Enheden vil nu blive ryddet. \n\nKontakt din organisations administrator, hvis du har spørgsmål."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Udskrivning er deaktiveret af <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-forbindelse"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Appen kører"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps, der bruger batteri"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Forstørrelse"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruger batteri"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps bruger batteri"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tryk for at se info om batteri- og dataforbrug"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nyhed: Forstørrelse af vindue"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Du kan nu forstørre dele af eller hele skærmen"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktivér i Indstillinger"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Luk"</string> </resources> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index ebbde3c9afef..b51ce5dd2547 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-Dienst"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Zeitzonen-Erkennung (keine Verbindung)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Die Daten auf deinem Gerät werden gelöscht."</string> <string name="factory_reset_message" msgid="2657049595153992213">"Die Admin-App kann nicht verwendet werden. Die Daten auf deinem Gerät werden nun gelöscht.\n\nBitte wende dich bei Fragen an den Administrator deiner Organisation."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Drucken wurde von <xliff:g id="OWNER_APP">%s</xliff:g> deaktiviert."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-Verbindung"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App wird ausgeführt"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Strom verbrauchende Apps"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Vergrößerung"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> verbraucht Strom"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> Apps verbrauchen Strom"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Für Details zur Akku- und Datennutzung tippen"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Neu: Fenstervergrößerung"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Du kannst das Display teilweise oder ganz vergrößern"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"In den Einstellungen aktivieren"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Schließen"</string> </resources> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 306d36e0ae9f..a794e480f54c 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Υπηρεσία GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Υπηρεσία ειδοποίησης αισθητήρα"</string> <string name="twilight_service" msgid="8964898045693187224">"Υπηρεσία Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Εντοπισμός ζώνης ώρας (χωρίς συνδεσιμότητα)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Η συσκευή σας θα διαγραφεί"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Δεν είναι δυνατή η χρήση της εφαρμογής διαχειριστή. Η συσκευή σας θα διαγραφεί.\n\nΕάν έχετε ερωτήσεις, επικοινωνήστε με τον διαχειριστή του οργανισμού σας."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Η εκτύπωση απενεργοποιήθηκε από τον χρήστη <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Σύνδεση USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Η εφαρμογή εκτελείται"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Εφαρμογές που καταναλώνουν μπαταρία"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Μεγιστοποίηση"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> χρησιμοποιεί μπαταρία"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> εφαρμογές χρησιμοποιούν μπαταρία"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Πατήστε για λεπτομέρειες σχετικά με τη χρήση μπαταρίας και δεδομένων"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Νέο: Μεγέθυνση παραθύρου"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Μεγεθύνετε μέρος ή ολόκληρη την οθόνη σας"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ενεργοποίηση στις Ρυθμίσεις"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Παράβλεψη"</string> </resources> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index a8706cbe32c2..74b835ea549c 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS service"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time zone detector (no connectivity)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string> <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string> diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index 57e2eae62f9c..8f8972c49b69 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS service"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time zone detector (no connectivity)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string> <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index 33ffbe386fc4..2421e2ac4595 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS service"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time zone detector (no connectivity)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string> <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index f5be6fd8c337..dd7b151eb34e 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS service"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time zone detector (no connectivity)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string> <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string> diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index cd3ff368c289..0e14345abbc0 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS Service"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time Zone Detector (No connectivity)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string> <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organization\'s admin."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 2d521b3290c2..780e48157780 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Servicio de Sistemas Globales de Navegación por Satélites (GNSS)"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Servicio de notificaciones del sensor"</string> <string name="twilight_service" msgid="8964898045693187224">"Servicio de Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de zona horaria (sin conexión)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Se borrarán los datos del dispositivo"</string> <string name="factory_reset_message" msgid="2657049595153992213">"No se puede usar la app de administrador. Ahora se borrará tu dispositivo.\n\nSi tienes preguntas, comunícate con el administrador de tu organización."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> inhabilitó la impresión."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Conexión USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App en ejecución"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps que consumen batería"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliación"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> está consumiendo batería"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps están consumiendo batería"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Presiona para obtener información sobre el uso de datos y de la batería"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nueva: Ampliación de ventanas"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Puedes ampliar toda tu pantalla o parte de ella"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activar en Configuración"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Descartar"</string> </resources> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index abc694686bee..3c6b9e202f3c 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Servicio GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Servicio de notificación de sensor"</string> <string name="twilight_service" msgid="8964898045693187224">"Servicio de Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de zona horaria (sin conexión)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Tu dispositivo se borrará"</string> <string name="factory_reset_message" msgid="2657049595153992213">"No se puede utilizar la aplicación de administración. Se borrarán todos los datos del dispositivo.\n\nSi tienes alguna pregunta, ponte en contacto con el administrador de tu organización."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ha inhabilitado la impresión."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Conexión USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplicación en ejecución"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicaciones que consumen batería"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliación"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> está usando la batería"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicaciones están usando la batería"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca para ver información detallada sobre el uso de datos y de la batería"</string> @@ -832,7 +832,7 @@ <string name="keyguard_password_enter_pin_password_code" msgid="7792964196473964340">"Introduce el código PIN para desbloquear."</string> <string name="keyguard_password_wrong_pin_code" msgid="8583732939138432793">"Código PIN incorrecto"</string> <string name="keyguard_label_text" msgid="3841953694564168384">"Para desbloquear el teléfono, pulsa la tecla de menú y, a continuación, pulsa 0."</string> - <string name="emergency_call_dialog_number_for_display" msgid="2978165477085612673">"Llamada de emergencia"</string> + <string name="emergency_call_dialog_number_for_display" msgid="2978165477085612673">"Número de emergencia"</string> <string name="lockscreen_carrier_default" msgid="6192313772955399160">"Sin servicio"</string> <string name="lockscreen_screen_locked" msgid="7364905540516041817">"Pantalla bloqueada"</string> <string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Pulsa la tecla de menú para desbloquear el teléfono o realizar una llamada de emergencia."</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nuevo: Lupa de ventanas"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Ahora puedes ampliar toda la pantalla o una parte"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activar en Ajustes"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Cerrar"</string> </resources> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index 130ef6e47b9f..152a35e0f9eb 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-teenus"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Anduri märguande teenus"</string> <string name="twilight_service" msgid="8964898045693187224">"Teenus Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Ajavööndi tuvastaja (ühenduvus puudub)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Seade kustutatakse"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Administraatori rakendust ei saa kasutada. Teie seade tühjendatakse nüüd.\n\nKui teil on küsimusi, võtke ühendust organisatsiooni administraatoriga."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Rakendus <xliff:g id="OWNER_APP">%s</xliff:g> on printimise keelanud."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-ühendus"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Rakendus töötab"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Rakendused kasutavad akutoidet"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Suurendus"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> kasutab akutoidet"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> rakendust kasutab akutoidet"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Aku ja andmekasutuse üksikasjade nägemiseks puudutage"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Uus: akna suurendaja"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Nüüd saab suurendada kogu ekraanikuva või osa sellest"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Lülitage sisse menüüs Seaded"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Loobu"</string> </resources> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index 5273a48fa3b5..4fa4d06e07ec 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS zerbitzua"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sentsorearen jakinarazpen-zerbitzua"</string> <string name="twilight_service" msgid="8964898045693187224">"Ilunabarreko zerbitzua"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Ordu-zonaren hautemailea (ez zaude konektatuta sarera)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Gailuko datuak ezabatu egingo dira"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Ezin da erabili administratzeko aplikazioa. Ezabatu egingo da gailuko eduki guztia.\n\nZalantzarik baduzu, jarri erakundeko administratzailearekin harremanetan."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> aplikazioak desgaitu egin du inprimatzeko aukera."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB konexioa"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikazio bat abian da"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Bateria kontsumitzen ari diren aplikazioak"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Lupa"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ari da bateria erabiltzen"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikazio ari dira bateria erabiltzen"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Sakatu bateria eta datuen erabilerari buruzko xehetasunak ikusteko"</string> @@ -500,7 +500,7 @@ <string name="permdesc_changeNetworkState" msgid="649341947816898736">"Sarearen konexioaren egoera aldatzeko baimena ematen die aplikazioei."</string> <string name="permlab_changeTetherState" msgid="9079611809931863861">"aldatu telefono bidezko konektagarritasuna"</string> <string name="permdesc_changeTetherState" msgid="3025129606422533085">"Partekatutako Interneterako konexioaren egoera aldatzeko baimena ematen die aplikazioei."</string> - <string name="permlab_accessWifiState" msgid="5552488500317911052">"ikusi wifi bidezko konexioak"</string> + <string name="permlab_accessWifiState" msgid="5552488500317911052">"ikusi wifi-konexioak"</string> <string name="permdesc_accessWifiState" msgid="6913641669259483363">"Wi-Fi sareei buruzko informazioa ikusteko baimena ematen die aplikazioei, adibidez, Wi-Fi konexioa aktibatuta dagoen eta konektatutako Wi-Fi gailuen izenak zein diren."</string> <string name="permlab_changeWifiState" msgid="7947824109713181554">"konektatu wifira edo deskonektatu bertatik"</string> <string name="permdesc_changeWifiState" msgid="7170350070554505384">"Wi-Fi sarbide-puntuetara konektatzeko edo haietatik deskonektatzeko baimena ematen die aplikazioei, baita Wi-Fi sareen gailu-konfigurazioari aldaketak egitekoa ere."</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Berria: leihoen lupa"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Orain, pantaila osoa edo haren zati bat handi dezakezu"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktibatu ezarpenetan"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Baztertu"</string> </resources> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 7596bab30f16..9efe16b563a1 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"سرویس GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"سرویس اعلان حسگر"</string> <string name="twilight_service" msgid="8964898045693187224">"سرویس Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"شناساگر منطقه زمانی (بدون اتصال)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"دستگاهتان پاک خواهد شد"</string> <string name="factory_reset_message" msgid="2657049595153992213">"برنامه سرپرست سیستم را نمیتوان استفاده کرد. دستگاه شما در این لحظه پاک میشود.\n\nاگر سؤالی دارید، با سرپرست سیستم سازمانتان تماس بگیرید."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> چاپ کردن را غیرفعال کرده است."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"اتصال USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"برنامه درحال اجرا"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"برنامههای مصرفکننده باتری"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"درشتنمایی"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> درحال استفاده کردن از باتری است"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> برنامه درحال استفاده کردن از باتری هستند"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"برای جزئیات مربوط به مصرف باتری و داده، ضربه بزنید"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"جدید: Window Magnifier"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"اکنون میتوانید بخشی از صفحه یا کل آن را درشت کنید"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"روشن کردن در «تنظیمات»"</string> + <string name="dismiss_action" msgid="1728820550388704784">"رد شدن"</string> </resources> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index d3373154196a..80c8ebe8853b 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-palvelu"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Anturin ilmoituspalvelu"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight-palvelu"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Aikavyöhykkeen tunnistin (ei yhteyttä)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Laitteen tiedot poistetaan"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Hallintasovellusta ei voi käyttää. Laitteen tiedot pyyhitään.\n\nPyydä ohjeita järjestelmänvalvojaltasi."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> on poistanut tulostuksen käytöstä."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-yhteys"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Sovellus käynnissä"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Akkua kuluttavat sovellukset"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Suurennus"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> käyttää akkua."</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> sovellusta käyttää akkua."</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Katso lisätietoja akun ja datan käytöstä napauttamalla."</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Uutta: ikkunan suurennus"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Voit nyt suurentaa näytön osittain tai kokonaan"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Laita päälle asetuksista"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Hylkää"</string> </resources> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index d2c89bc8d842..8bc6d37a8ffc 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -201,6 +201,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Service GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Service de notification de capteur"</string> <string name="twilight_service" msgid="8964898045693187224">"Service de crépuscule"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Détecteur de fuseau horaire (aucune connectivité)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Le contenu de votre appareil sera effacé"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Impossible d\'utiliser l\'application d\'administration. Les données de votre appareil vont maintenant être effacées.\n\nSi vous avez des questions, communiquez avec l\'administrateur de votre organisation."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Impression désactivée par <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -290,8 +291,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Connexion USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Application en cours d\'exécution"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Applications qui sollicitent la pile"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Agrandissement"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sollicite la pile"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> applications sollicitent la pile"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Touchez pour afficher des détails sur l\'utilisation de la pile et des données"</string> @@ -2224,12 +2224,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nouveauté : Loupe de fenêtre"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Vous pouvez agrandir une partie ou la totalité de votre écran"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activer dans les paramètres"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Fermer"</string> </resources> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 1992068a4a85..7d5e10bd5686 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -201,6 +201,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Service GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Service de notification du capteur"</string> <string name="twilight_service" msgid="8964898045693187224">"Service Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Outil de détection du fuseau horaire (aucune connectivité)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Les données de votre appareil vont être effacées"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Impossible d\'utiliser l\'application d\'administration. Les données de votre appareil vont maintenant être effacées.\n\nSi vous avez des questions, contactez l\'administrateur de votre organisation."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Impression désactivée par <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -290,8 +291,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Connexion USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Application en cours d\'exécution"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Applications utilisant la batterie"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Agrandissement"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> utilise la batterie"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> applications utilisent la batterie"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Appuyer pour obtenir des informations sur l\'utilisation de la batterie et des données"</string> @@ -1823,7 +1823,7 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"Mis à jour par votre administrateur"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"Supprimé par votre administrateur"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Pour prolonger l\'autonomie de la batterie, l\'économiseur de batterie :\n\n·• active le thème sombre ;\n·• désactive ou restreint les activités en arrière-plan, certains effets visuels et d\'autres fonctionnalités, comme \"Hey Google\".\n\n"<annotation id="url">"En savoir plus"</annotation></string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Pour prolonger l\'autonomie de la batterie, l\'économiseur de batterie :\n\n • active le thème sombre ;\n • désactive ou restreint les activités en arrière-plan, certains effets visuels et d\'autres fonctionnalités, comme \"Hey Google\".\n\n"<annotation id="url">"En savoir plus"</annotation></string> <string name="battery_saver_description" msgid="6794188153647295212">"Pour prolonger l\'autonomie de la batterie, l\'économiseur de batterie :\n\n• active le thème sombre ;\n • désactive ou restreint les activités en arrière-plan, certains effets visuels et d\'autres fonctionnalités, comme \"Hey Google\"."</string> <string name="data_saver_description" msgid="4995164271550590517">"Pour réduire la consommation de données, l\'économiseur de données empêche certaines applications d\'envoyer ou de recevoir des données en arrière-plan. Ainsi, les applications que vous utilisez peuvent toujours accéder aux données, mais pas en permanence. Par exemple, il se peut que les images ne s\'affichent pas tant que vous n\'appuyez pas dessus."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Activer l\'économiseur de données ?"</string> @@ -2224,12 +2224,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nouveau : agrandissement de la fenêtre"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Vous pouvez agrandir tout ou partie de l\'écran"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activer dans les paramètres"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Fermer"</string> </resources> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index 7583502fb988..c1d870338599 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Servizo GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Servizo de notificacións dos sensores"</string> <string name="twilight_service" msgid="8964898045693187224">"Servizo Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de fuso horario (non require conexión)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Borrarase o teu dispositivo"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Non se pode utilizar a aplicación de administración. Borrarase o teu dispositivo.\n\nSe tes preguntas, contacta co administrador da organización."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> desactivou a impresión."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"conexión USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Estase executando a aplicación"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicacións que consomen batería"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliación"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"A aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> está consumindo batería"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicacións están consumindo batería"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca para obter información sobre o uso de datos e a batería"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nova función: Lupa de ventá"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Agora podes ampliar toda a pantalla ou parte dela"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activar en Configuración"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Ignorar"</string> </resources> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index 6f140c4b5d85..794b7a78bb0e 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS સેવા"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"સેન્સર નોટિફિકેશન સેવા"</string> <string name="twilight_service" msgid="8964898045693187224">"ટ્વાઇલાઇટ સેવા"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"સમય ઝોન શોધવાની સુવિધા (કનેક્ટિવિટી જરૂરી નથી)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"તમારું ઉપકરણ કાઢી નાખવામાં આવશે"</string> <string name="factory_reset_message" msgid="2657049595153992213">"વ્યવસ્થાપક ઍપનો ઉપયોગ કરી શકાશે નહીં. તમારું ઉપકરણ હવે કાઢી નાખવામાં આવશે.\n\nજો તમને પ્રશ્નો હોય, તો તમારી સંસ્થાના વ્યવસ્થાપકનો સંપર્ક કરો."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> દ્વારા પ્રિન્ટ કરવાનું બંધ કરાયું છે."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB કનેક્શન"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ઍપ ચાલી રહ્યું છે"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ઍપ બૅટરીનો વપરાશ કરી રહ્યાં છે"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"મોટું કરવાની સુવિધા"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> બૅટરીનો ઉપયોગ કરી રહ્યું છે"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ઍપ બૅટરીનો ઉપયોગ કરી રહ્યાં છે"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"બૅટરી અને ડેટા વપરાશ વિશેની વિગતો માટે ટૅપ કરો"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"નવી: વિંડો મોટી કરવાની સુવિધા"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"હવે તમે તમારી કેટલીક કે આખી સ્ક્રીનને મોટી કરી શકો છો"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"સેટિંગમાં ચાલુ કરો"</string> + <string name="dismiss_action" msgid="1728820550388704784">"છોડી દો"</string> </resources> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 5892dab23628..dc44fbaf1bae 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"जीएनएसएस सेवा"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"सेंसर से जुड़ी सूचना सेवा"</string> <string name="twilight_service" msgid="8964898045693187224">"ट्वाइलाइट समय बताने वाली सेवा"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"समय क्षेत्र का पता लगाने वाली सुविधा (ऑफ़लाइन होने पर)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"आपके डिवाइस को मिटा दिया जाएगा"</string> <string name="factory_reset_message" msgid="2657049595153992213">"एडमिन ऐप्लिकेशन का इस्तेमाल नहीं किया जा सकता. आपके डिवाइस पर मौजूद डेटा अब मिटा दिया जाएगा.\n\nअगर आप कुछ पूछना चाहते हैं तो, अपने संगठन के एडमिन से संपर्क करें."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ने प्रिंटिंग सुविधा बंद कर दी है."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB कनेक्शन"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ऐप अभी इस्तेमाल हो रहा है"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"बैटरी की खपत करने वाले ऐप"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ज़ूम करने की सुविधा"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> बैटरी का इस्तेमाल कर रहा है"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ऐप बैटरी का इस्तेमाल कर रहे हैं"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"बैटरी और डेटा खर्च की जानकारी के लिए छूएं"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"नई सुविधा: विंडो को ज़ूम करके देखने की सुविधा"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"अब अपनी पूरी स्क्रीन या कुछ हिस्से को ज़ूम करके देख सकते हैं"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"सेटिंग में जाकर, इस सुविधा को चालू करें"</string> + <string name="dismiss_action" msgid="1728820550388704784">"खारिज करें"</string> </resources> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index f4d984275576..deaac3fb5bc5 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -201,6 +201,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Usluga GNSS-a"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Usluga Obavijesti senzora"</string> <string name="twilight_service" msgid="8964898045693187224">"Usluga Sumrak"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detektor vremenske zone (nije povezan)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Uređaj će se izbrisati"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Administratorska aplikacija ne može se upotrebljavati. Uređaj će se izbrisati.\n\nAko imate pitanja, obratite se administratoru organizacije."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Ispis je onemogućila aplikacija <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -290,8 +291,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB veza"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Izvodi se aplikacija"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije troše bateriju"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Povećavanje"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> koristi bateriju"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Broj aplikacija koje koriste bateriju: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite da biste vidjeli pojedinosti o potrošnji baterije i podatkovnom prometu"</string> @@ -2224,12 +2224,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novo: alat za povećanje prozora"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Sad možete povećati dio zaslona ili cijeli zaslon"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Uključite u Postavkama"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Odbaci"</string> </resources> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index bff17731ac84..c408395cbc34 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-szolgáltatás"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Szenzoros értesítési szolgáltatás"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight szolgáltatás"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Időzóna-felismerő (Offline)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"A rendszer törölni fogja eszközét"</string> <string name="factory_reset_message" msgid="2657049595153992213">"A rendszergazdai alkalmazás nem használható. A rendszer most törli az eszközt.\n\nKérdéseivel forduljon szervezete rendszergazdájához."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"A(z) <xliff:g id="OWNER_APP">%s</xliff:g> letiltotta a nyomtatást."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-kapcsolat"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Jelenleg futó alkalmazás"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Akkumulátort használó alkalmazások"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Nagyítás"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás használja az akkumulátort"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> alkalmazás használja az akkumulátort"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Koppintson az akkumulátor- és adathasználat részleteinek megtekintéséhez"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Újdonság: Ablaknagyító"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Ezután nagyíthatja a képernyőt vagy egy részét"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Bekapcsolás a Beállításokban"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Elvetés"</string> </resources> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index 1f2e642c74c6..b1db764ee0fa 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS ծառայություն"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Տվիչների ծանուցումների մշակման ծառայություն"</string> <string name="twilight_service" msgid="8964898045693187224">"Մթնշաղի սկիզբը որոշող ծառայություն"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Ժամային գոտու դետեկտոր (աշխատում է առանց ինտերնետի)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Ձեր սարքը ջնջվելու է"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Հնարավոր չէ օգտագործել ադմինիստրատորի հավելվածը։ Ձեր սարքից բոլոր տվյալները կջնջվեն։\n\nՀարցեր ունենալու դեպքում դիմեք ձեր կազմակերպության ադմինիստրատորին։"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Տպումն անջատված է <xliff:g id="OWNER_APP">%s</xliff:g> հավելվածի կողմից։"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB կապակցում"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Հավելվածն աշխատում է"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Մարտկոցի լիցքը ծախսող հավելվածներ"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Խոշորացում"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"«<xliff:g id="APP_NAME">%1$s</xliff:g>» հավելվածը ծախսում է մարտկոցի լիցքը"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> հավելված ծախսում է մարտկոցի լիցքը"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Հպեք՝ մարտկոցի և թրաֆիկի մանրամասները տեսնելու համար"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Նոր գործառույթ. Պատուհանի խոշորացույց"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Այժմ կարող եք խոշորացնել ամբողջ էկրանը կամ դրա մի մասը"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Միացնել կարգավորումներում"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Փակել"</string> </resources> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 4f26eb687082..fc82c22aab3a 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Layanan GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Layanan Notifikasi Sensor"</string> <string name="twilight_service" msgid="8964898045693187224">"Layanan Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Pendeteksi Zona Waktu (Tidak ada konektivitas)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Perangkat akan dihapus"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Aplikasi admin tidak dapat digunakan. Perangkat Anda kini akan dihapus.\n\nJika ada pertanyaan, hubungi admin organisasi."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Fitur pencetakan dinonaktifkan oleh <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Sambungan USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikasi berjalan"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikasi yang menggunakan baterai"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Pembesaran"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang menggunakan baterai"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikasi sedang meggunakan baterai"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ketuk untuk melihat detail penggunaan baterai dan data"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Baru: Pembesar Jendela"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Anda bisa memperbesar sebagian atau seluruh layar"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktifkan di Setelan"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Tutup"</string> </resources> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index d5539a395206..456f518e87ca 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-þjónusta"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Tilkynningaþjónusta nema"</string> <string name="twilight_service" msgid="8964898045693187224">"Ljósaskiptaþjónusta"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tímabeltisgreinir (engin tenging)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Tækið verður hreinsað"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Ekki er hægt að nota stjórnunarforritið. Tækinu verður eytt.\n\nEf spurningar vakna skaltu hafa samband við kerfisstjóra fyrirtækisins."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> lokaði á prentun."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-tenging"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Forrit er í gangi"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Forrit sem nota rafhlöðuorku"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Stækkun"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> notar rafhlöðuorku"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> forrit nota rafhlöðuorku"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ýttu til að fá upplýsingar um rafhlöðu- og gagnanotkun"</string> @@ -1801,7 +1801,7 @@ <string name="package_deleted_device_owner" msgid="2292335928930293023">"Kerfisstjóri eyddi"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"Í lagi"</string> <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Til að auka rafhlöðuendingu gerir rafhlöðusparnaður eftirfarandi:\n\n•·Kveikir á dökku þema\n•·Slekkur á eða takmarkar bakgrunnsvirkni, tilteknar myndbrellur og aðra eiginleika eins og „Ok Google“\n\n"<annotation id="url">"Frekari upplýsingar"</annotation></string> - <string name="battery_saver_description" msgid="6794188153647295212">"Til að auka rafhlöðuendingu gerir rafhlöðusparnaður eftirfarandi:\n\n•·Kveikir á dökku þema\n•·Slekkur á eða takmarkar bakgrunnsvirkni, tilteknar myndbrellur og aðra eiginleika eins og „Ok Google“"</string> + <string name="battery_saver_description" msgid="6794188153647295212">"Til að auka rafhlöðuendingu gerir rafhlöðusparnaður eftirfarandi:\n\n• Kveikir á dökku þema\n• Slekkur á eða takmarkar bakgrunnsvirkni, tilteknar myndbrellur og aðra eiginleika eins og „Ok Google“"</string> <string name="data_saver_description" msgid="4995164271550590517">"Gagnasparnaður getur hjálpað til við að draga úr gagnanotkun með því að hindra forrit í að senda eða sækja gögn í bakgrunni. Forrit sem er í notkun getur náð í gögn, en gerir það kannski sjaldnar. Niðurstaðan getur verið, svo dæmi sé tekið, að myndir eru ekki birtar fyrr en þú ýtir á þær."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Kveikja á gagnasparnaði?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Kveikja"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nýtt: Gluggastækkun"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Nú geturðu stækkað allan skjáinn eða hluta hans"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Kveikja á í stillingum"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Hunsa"</string> </resources> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 152cfee90863..e89145bdd013 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Servizio GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Servizio di notifica dei sensori"</string> <string name="twilight_service" msgid="8964898045693187224">"Servizio Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Rilevatore di fuso orario (connessione a Internet non necessaria)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Il dispositivo verrà resettato"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Impossibile usare l\'app di amministrazione. Il dispositivo verrà resettato.\n\nPer eventuali domande, contatta l\'amministratore della tua organizzazione."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Stampa disattivata da <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -1451,7 +1452,7 @@ <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Tocca per uscire dall\'app di guida."</string> <string name="back_button_label" msgid="4078224038025043387">"Indietro"</string> <string name="next_button_label" msgid="6040209156399907780">"Avanti"</string> - <string name="skip_button_label" msgid="3566599811326688389">"Ignora"</string> + <string name="skip_button_label" msgid="3566599811326688389">"Salta"</string> <string name="no_matches" msgid="6472699895759164599">"Nessuna corrispondenza"</string> <string name="find_on_page" msgid="5400537367077438198">"Trova nella pagina"</string> <plurals name="matches_found" formatted="false" msgid="1101758718194295554"> @@ -1799,8 +1800,8 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"Aggiornato dall\'amministratore"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminato dall\'amministratore"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Per estendere la durata della batteria, la funzionalità di risparmio energetico:\n\n• Attiva il tema scuro\n• Disattiva o limita le attività in background, alcuni effetti visivi e altre funzionalità come \"Ok Google\"\n\n"<annotation id="url">"Ulteriori informazioni"</annotation></string> - <string name="battery_saver_description" msgid="6794188153647295212">"Per estendere la durata della batteria, la funzionalità di risparmio energetico:\n\n• Attiva il tema scuro\n• Disattiva o limita le attività in background, alcuni effetti visivi e altre funzionalità come \"Ok Google\""</string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Per estendere la durata della batteria, la funzionalità di risparmio energetico:\n\n• Attiva il tema scuro\n• Disattiva o limita le attività in background, alcuni effetti visivi e altre funzionalità come \"Hey Google\"\n\n"<annotation id="url">"Scopri di più"</annotation></string> + <string name="battery_saver_description" msgid="6794188153647295212">"Per estendere la durata della batteria, la funzionalità di risparmio energetico:\n\n• Attiva il tema scuro\n• Disattiva o limita le attività in background, alcuni effetti visivi e altre funzionalità come \"Hey Google\""</string> <string name="data_saver_description" msgid="4995164271550590517">"Per contribuire a ridurre l\'utilizzo dei dati, la funzione Risparmio dati impedisce ad alcune app di inviare o ricevere dati in background. Un\'app in uso può accedere ai dati, ma potrebbe farlo con meno frequenza. Esempio: le immagini non vengono visualizzate finché non le tocchi."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Attivare Risparmio dati?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Attiva"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 5ae9436dd1b3..a8810ab901fd 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"שירות GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"שירות להתראות מחיישנים"</string> <string name="twilight_service" msgid="8964898045693187224">"שירות דמדומים"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"מזהה אזור זמן (ללא צורך בקישוריות)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"תתבצע מחיקה של המכשיר"</string> <string name="factory_reset_message" msgid="2657049595153992213">"לא ניתן להשתמש באפליקציה של מנהל המערכת.\n\nאם יש לך שאלות, יש ליצור קשר עם מנהל המערכת של הארגון."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"ההדפסה הושבתה על ידי <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"חיבור USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"אפליקציה פועלת"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"אפליקציות שמרוקנות את הסוללה"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"הגדלה"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> משתמשת בסוללה"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> אפליקציות משתמשות בסוללה"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"הקש לקבלת פרטים על צריכה של נתונים וסוללה"</string> @@ -2258,12 +2258,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"חדש: Window Magnifier"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"עכשיו אפשר להגדיל את המסך או חלקים ממנו"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"הפעלה בהגדרות"</string> + <string name="dismiss_action" msgid="1728820550388704784">"סגירה"</string> </resources> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 7a54a1594501..079598b03c65 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS サービス"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"センサー通知サービス"</string> <string name="twilight_service" msgid="8964898045693187224">"トワイライト サービス"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time Zone Detector(未接続)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"デバイスのデータが消去されます"</string> <string name="factory_reset_message" msgid="2657049595153992213">"管理アプリを使用できません。デバイスのデータはこれから消去されます。\n\nご不明な点がある場合は、組織の管理者にお問い合わせください。"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"「<xliff:g id="OWNER_APP">%s</xliff:g>」により印刷は無効にされています。"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB 接続"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"実行中のアプリ"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"電池を消費しているアプリ"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"拡大"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」が電池を使用しています"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個のアプリが電池を使用しています"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"タップして電池やデータの使用量を確認"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"新機能: Window Magnifier"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"画面の一部または全体を拡大できるようになりました"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"[設定] で ON にする"</string> + <string name="dismiss_action" msgid="1728820550388704784">"閉じる"</string> </resources> diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index 1653cb91c3fb..22d69d613f06 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS სერვისი"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"სენსორის შეტყობინების სერვისი"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight სერვისი"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"სასაათო სარტყლის დეტექტორი (კავშირის გარეშე)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"თქვენი მოწყობილობა წაიშლება"</string> <string name="factory_reset_message" msgid="2657049595153992213">"ადმინისტრატორის აპის გამოყენება ვერ მოხერხდება. თქვენი მოწყობილობა ახლა ამოიშლება.\n\nთუ შეკითხვები გაქვთ, დაუკავშირდით თქვენი ორგანიზაციის ადმინისტრატორს."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"ბეჭდვა გათიშულია <xliff:g id="OWNER_APP">%s</xliff:g>-ის მიერ."</string> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index 635fed7f6bf1..464b79837972 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS қызметі"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Датчик хабарландыруы қызметі"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight қызметі"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Уақыт белдеуін анықтағыш (қосылу мүмкіндігі жоқ)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Құрылғыңыздағы деректер өшіріледі"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Әкімші қолданбасын пайдалану мүмкін емес. Қазір құрылғыдағы деректер өшіріледі\n\nСұрақтарыңыз болса, ұйым әкімшісіне хабарласыңыз."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Басып шығаруды <xliff:g id="OWNER_APP">%s</xliff:g> өшірді."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB байланысы"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Қолданба қосулы"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Батареяны пайдаланып жатқан қолданбалар"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ұлғайту"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> батареяны пайдалануда"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> қолданба батареяны пайдалануда"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батарея мен деректер трафигі туралы білу үшін түртіңіз"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Жаңа: Window Magnifier"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Енді экранның бір бөлігін не барлығын ұлғайта аласыз."</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Параметрлер бөлімінен қосу"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Қабылдамау"</string> </resources> diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml index 1160a40bb899..823a5746ff46 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"សេវាកម្ម GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"សេវាកម្មជូនដំណឹងឧបករណ៍ចាប់សញ្ញា"</string> <string name="twilight_service" msgid="8964898045693187224">"សេវាកម្មព្រលប់"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ឧបករណ៍សម្គាល់ល្វែងម៉ោង (គ្មានការតភ្ជាប់ទេ)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"ឧបករណ៍របស់អ្នកនឹងត្រូវបានលុប"</string> <string name="factory_reset_message" msgid="2657049595153992213">"មិនអាចប្រើកម្មវិធីអ្នកគ្រប់គ្រងបានទេ។ ឧបករណ៍របស់អ្នកនឹងលុបឥឡូវនេះ។\n\nប្រសិនបើអ្នកមានសំណួរផ្សេងៗ សូមទាក់ទងទៅអ្នកគ្រប់គ្រងស្ថាប័នរបស់អ្នក។"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"ការបោះពុម្ពត្រូវបានបិទដោយ <xliff:g id="OWNER_APP">%s</xliff:g> ។"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"ការតភ្ជាប់ USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"កម្មវិធីដែលកំពុងដំណើរការ"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"កម្មវិធីដែលកំពុងប្រើថ្ម"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ការពង្រីក"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងប្រើថ្ម"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"កម្មវិធីចំនួន <xliff:g id="NUMBER">%1$d</xliff:g> កំពុងប្រើថ្ម"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ចុចដើម្បីមើលព័ត៌មានលម្អិតអំពីការប្រើប្រាស់ទិន្នន័យ និងថ្ម"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ថ្មី៖ កម្មវិធីពង្រីកវិនដូ"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ឥឡូវនេះ អ្នកអាចពង្រីកផ្នែកខ្លះ ឬទាំងអស់នៃអេក្រង់របស់អ្នក"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"បើកនៅក្នុងការកំណត់"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ច្រានចោល"</string> </resources> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index 8eb3467dd32e..bac30efe0c1e 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS ಸೇವೆ"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"ಸೆನ್ಸರ್ ಅಧಿಸೂಚನೆ ಸೇವೆ"</string> <string name="twilight_service" msgid="8964898045693187224">"ಟ್ವಿಲೈಟ್ ಸೇವೆ"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ಸಮಯವಲಯ ಡಿಟೆಕ್ಟರ್ (ಯಾವುದೇ ಸಂಪರ್ಕ ಕಲ್ಪಿಸುವಿಕೆ ಇಲ್ಲ)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ"</string> <string name="factory_reset_message" msgid="2657049595153992213">"ನಿರ್ವಹಣೆ ಅಪ್ಲಿಕೇಶನ್ ಬಳಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ನಿಮ್ಮ ಸಾಧನವನ್ನು ಇದೀಗ ಅಳಿಸಲಾಗುತ್ತದೆ.\n\nನಿಮ್ಮಲ್ಲಿ ಪ್ರಶ್ನೆಗಳಿದ್ದರೆ, ನಿಮ್ಮ ಸಂಸ್ಥೆಯ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ಮೂಲಕ ಪ್ರಿಂಟಿಂಗ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB ಸಂಪರ್ಕ"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App ರನ್ ಆಗುತ್ತಿದೆ"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ಅಪ್ಲಿಕೇಶನ್ಗಳು ಬ್ಯಾಟರಿಯನ್ನು ಉಪಯೋಗಿಸುತ್ತಿವೆ"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ಹಿಗ್ಗಿಸುವಿಕೆ"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಆ್ಯಪ್, ಬ್ಯಾಟರಿಯನ್ನು ಬಳಸುತ್ತಿದೆ"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ಅಪ್ಲಿಕೇಶನ್ಗಳು ಬ್ಯಾಟರಿ ಬಳಸುತ್ತಿವೆ"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ಬ್ಯಾಟರಿ,ಡೇಟಾ ಬಳಕೆಯ ವಿವರಗಳಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ಹೊಸದು: ವಿಂಡೋ ಮ್ಯಾಗ್ನಿಫೈಯರ್"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ಈಗ ಕೆಲವು ಅಥವಾ ಎಲ್ಲಾ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಹಿಗ್ಗಿಸಬಹುದು"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಆನ್ ಮಾಡಿ"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ವಜಾಗೊಳಿಸಿ"</string> </resources> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 46b4a1b3ed1c..00eb66f3898b 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS 서비스"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"센서 알림 서비스"</string> <string name="twilight_service" msgid="8964898045693187224">"새벽 서비스"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"시간대 감지(연결되지 않음)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"기기가 삭제됩니다."</string> <string name="factory_reset_message" msgid="2657049595153992213">"관리자 앱을 사용할 수 없습니다. 곧 기기가 삭제됩니다.\n\n궁금한 점이 있으면 조직의 관리자에게 문의하세요."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g>에 의해 사용 중지되었습니다."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB 연결"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"실행 중인 앱"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"배터리를 소모하는 앱"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"확대"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 배터리 사용 중"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"앱 <xliff:g id="NUMBER">%1$d</xliff:g>개에서 배터리 사용 중"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"탭하여 배터리 및 데이터 사용량 확인"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"새로운 기능: 창 돋보기"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"이제 화면 일부 또는 전체를 확대할 수 있습니다."</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"설정에서 사용 설정"</string> + <string name="dismiss_action" msgid="1728820550388704784">"닫기"</string> </resources> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index bb005f3281fc..7c1fb98d2d22 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS кызматы"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Сенсордун билдирмелеринин кызматы"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight кызматы"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Убакыт алкагын аныктагыч (байланыш жок)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Түзмөгүңүз тазаланат"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Түзмөктү башкаруучу колдонмо жараксыз. Түзмөгүңүз азыр тазаланат.\n\nСуроолоруңуз болсо, ишканаңыздын администраторуна кайрылыңыз."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Басып чыгаруу <xliff:g id="OWNER_APP">%s</xliff:g> тарабынан өчүрүлдү."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB аркылуу туташуу"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Колдонмо иштеп жатат"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Колдонмолор батареяңызды коротууда"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Чоңойтуу"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу батареяны пайдаланып жатат"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> колдонмо батареяны пайдаланып жатат"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батареянын кубаты жана трафиктин көлөмү жөнүндө билүү үчүн таптап коюңуз"</string> @@ -1800,8 +1800,8 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"Администраторуңуз жаңыртып койгон"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"Администраторуңуз жок кылып салган"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"ЖАРАЙТ"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Батареянын мөөнөтүн узартуу үчүн Батареяны үнөмдөгүч режими төмөнкүлөрдү аткарат:\n\n• Караңгы теманы күйгүзөт\n• Фондогу аракеттерди, айрым визуалдык эффекттерди жана \"Окей Google\" сыяктуу башка функцияларды өчүрөт же чектейт\n\n"<annotation id="url">"Кеңири маалымат"</annotation></string> - <string name="battery_saver_description" msgid="6794188153647295212">"Батареянын мөөнөтүн узартуу үчүн Батареяны үнөмдөгүч режими:\n\n• Караңгы теманы күйгүзөт\n• Фондогу аракеттерди, айрым визуалдык эффекттерди жана \"Окей Google\" сыяктуу башка функцияларды өчүрөт же чектейт"</string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Батареяны көбүрөөк убакытка жеткирүү үчүн Батареяны үнөмдөгүч режиминде:\n\n• Караңгы тема күйгүзүлөт\n• Фондогу аракеттерди, айрым визуалдык эффекттерди жана \"Окей Google\" сыяктуу башка функцияларды өчүрөт же чектейт\n\n"<annotation id="url">"Кеңири маалымат"</annotation></string> + <string name="battery_saver_description" msgid="6794188153647295212">"Батареяны көбүрөөк убакытка жеткирүү үчүн Батареяны үнөмдөгүч режими:\n\n• Караңгы тема күйгүзүлөт\n• Фондогу аракеттерди, айрым визуалдык эффекттерди жана \"Окей Google\" сыяктуу башка функцияларды өчүрөт же чектейт"</string> <string name="data_saver_description" msgid="4995164271550590517">"Трафикти үнөмдөө режиминде айрым колдонмолор дайын-даректерди фондо өткөрө алышпайт. Учурда сиз пайдаланып жаткан колдонмо дайын-даректерди жөнөтүп/ала алат, бирок адаттагыдан азыраак өткөргөндүктөн, анын айрым функциялары талаптагыдай иштебей коюшу мүмкүн. Мисалы, сүрөттөр басылмайынча жүктөлбөйт."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Трафикти үнөмдөө режимин иштетесизби?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Күйгүзүү"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Жаңы функция: Терезе чоңойткуч"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Эми толук экранды же анын бөлүгүн чоңойто аласыз"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Жөндөөлөрдөн күйгүзүү"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Жабуу"</string> </resources> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index 8e4e467fdd50..72bd141424fa 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"ບໍລິການ GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"ບໍລິການການແຈ້ງເຕືອນເຊັນເຊີ"</string> <string name="twilight_service" msgid="8964898045693187224">"ບໍລິການ Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ຕົວກວດຫາເຂດເວລາ (ບໍ່ມີການເຊື່ອມຕໍ່)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"ອຸປະກອນຂອງທ່ານຈະຖືກລຶບ"</string> <string name="factory_reset_message" msgid="2657049595153992213">"ບໍ່ສາມາດໃຊ້ແອັບຜູ້ເບິ່ງແຍງລະບົບໄດ້. ອຸປະກອນຂອງທ່ານຈະຖືກລຶບຂໍ້ມູນໃນຕອນນີ້.\n\nຫາກທ່ານມີຄຳຖາມ, ໃຫ້ຕິດຕໍ່ຜູ້ເບິ່ງແຍງລະບົບອົງກອນຂອງທ່ານ."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"ການພິມຖືກປິດໄວ້ໂດຍ <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"ການເຊື່ອມຕໍ່ USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ແອັບກຳລັງເຮັດວຽກ"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ແອັບທີ່ກຳລັງໃຊ້ແບັດເຕີຣີ"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ການຂະຫຍາຍ"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງໃຊ້ແບັດເຕີຣີຢູ່"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ແອັບກຳລັງໃຊ້ແບັດເຕີຣີຢູ່"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ແຕະເພື່ອເບິ່ງລາຍລະອຽດການນຳໃຊ້ແບັດເຕີຣີ ແລະ ອິນເຕີເນັດ"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ໃໝ່: ຕົວຂະຫຍາຍໜ້າຈໍ"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ຕອນນີ້ທ່ານສາມາດຂະຫຍາຍບາງສ່ວນ ຫຼື ທັງໝົດຂອງໜ້າຈໍໄດ້"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ເປີດໃຊ້ໃນການຕັ້ງຄ່າ"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ປິດໄວ້"</string> </resources> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index a9227163bf6b..a4e1756419f3 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS paslauga"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Jutiklių pranešimų paslauga"</string> <string name="twilight_service" msgid="8964898045693187224">"Paslauga „Twilight“"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Laiko juostos aptikimo priemonė (nėra ryšio)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Įrenginys bus ištrintas"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Administratoriaus programos negalima naudoti. Dabar įrenginio duomenys bus ištrinti.\n\nJei turite klausimų, susisiekite su organizacijos administratoriumi."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Neleidžiama spausdinti (<xliff:g id="OWNER_APP">%s</xliff:g>)."</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB jungtis"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Programa paleista"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programos, naudojančios akumuliatoriaus energiją"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Didinimas"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ naudoja akumuliatoriaus energiją"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Programų, naudojančių akumuliatoriaus energiją: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Palieskite ir sužinokite išsamios informacijos apie akumuliatoriaus bei duomenų naudojimą"</string> @@ -2258,12 +2258,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nauja: „Window Magnifier“"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Dabar galite padidinti dalį ekrano ar jį visą"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Įjungti nustatymuose"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Atmesti"</string> </resources> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 2fec712d0cd0..088e78d1ea3f 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -201,6 +201,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS pakalpojums"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensoru paziņojumu pakalpojums"</string> <string name="twilight_service" msgid="8964898045693187224">"Krēslas noteikšanas pakalpojums"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Laika joslas noteikšanas rīks (nav savienojuma)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Jūsu ierīces dati tiks dzēsti"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Administratora lietotni nevar izmantot. Ierīcē saglabātie dati tiks dzēsti.\n\nJa jums ir kādi jautājumi, sazinieties ar savas organizācijas administratoru."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Drukāšanu atspējoja <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -290,8 +291,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB savienojums"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Lietotne darbojas"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Lietotnes, kas patērē akumulatora jaudu"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Palielinājums"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> izmanto akumulatoru"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> lietotne(-es) izmanto akumulatoru"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Pieskarieties, lai skatītu detalizētu informāciju par akumulatora un datu lietojumu"</string> @@ -2224,12 +2224,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Jaunums: funkcija Window Magnifier"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Tagad varat palielināt ekrāna daļu vai visu ekrānu"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ieslēgt sadaļā Iestatījumi"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Nerādīt"</string> </resources> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index 3d02757d8ed9..23a84c67afc3 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Услуга GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Услуга за известување од сензорот"</string> <string name="twilight_service" msgid="8964898045693187224">"Услуга за самрак"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Откривач на временска зона (не може да се поврзе)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Уредот ќе се избрише"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Апликацијата на администраторот не може да се користи. Уредот ќе се избрише сега.\n\nАко имате прашања, контактирајте со администраторот на организацијата."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Печатењето е оневозможено од <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-врска"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Апликацијата работи"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апликации што ја трошат батеријата"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Зголемување"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> користи батерија"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> апликации користат батерија"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Допрете за детали за батеријата и потрошениот сообраќај"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Ново: „Лупа за прозорци“"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Сега може се зголеми целиот екран или само дел"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Вклучи во „Поставки“"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Отфрли"</string> </resources> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index 583c46e325a3..1c89b333ff1e 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS സേവനം"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"സെൻസർ അറിയിപ്പ് സേവനം"</string> <string name="twilight_service" msgid="8964898045693187224">"സന്ധ്യാസമയത്തെ സേവനം"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"സമയമേഖല കണ്ടെത്താനുള്ള സംവിധാനം (കണക്റ്റിവിറ്റി ഇല്ല)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"നിങ്ങളുടെ ഉപകരണം മായ്ക്കും"</string> <string name="factory_reset_message" msgid="2657049595153992213">"അഡ്മിൻ ആപ്പ് ഉപയോഗിക്കാനാകില്ല. നിങ്ങളുടെ ഉപകരണം ഇപ്പോൾ മായ്ക്കപ്പെടും.\n\nനിങ്ങൾക്ക് ചോദ്യങ്ങൾ ഉണ്ടെങ്കിൽ, നിങ്ങളുടെ സ്ഥാപനത്തിന്റെ അഡ്മിനെ ബന്ധപ്പെടുക."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> പ്രിന്റിംഗ് പ്രവർത്തനരഹിതമാക്കി."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB കണക്ഷൻ"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ആപ്പ് പ്രവർത്തിക്കുന്നു"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ആപ്പുകൾ ബാറ്ററി ഉപയോഗിക്കുന്നു"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"മാഗ്നിഫിക്കേഷൻ"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ബാറ്ററി ഉപയോഗിക്കുന്നു"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ആപ്പുകൾ ബാറ്ററി ഉപയോഗിക്കുന്നു"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ബാറ്ററി, ഡാറ്റ ഉപയോഗം എന്നിവയുടെ വിശദാംശങ്ങളറിയാൻ ടാപ്പുചെയ്യുക"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"പുതിയത്: വിൻഡോ മാഗ്നിഫൈയർ"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"സ്ക്രീനിന്റെ ഭാഗങ്ങളോ മുഴുവനുമോ മാഗ്നിഫൈ ചെയ്യാം"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ക്രമീകരണത്തിൽ ഓണാക്കുക"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ഡിസ്മിസ് ചെയ്യുക"</string> </resources> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index 081e17065b56..919112a1bd95 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -48,7 +48,7 @@ <string name="invalidPin" msgid="7542498253319440408">"4-8 тооноос бүтэх PIN-г бичнэ үү."</string> <string name="invalidPuk" msgid="8831151490931907083">"8-с цөөнгүй тооноос бүтэх PUK-г бичнэ үү."</string> <string name="needPuk" msgid="7321876090152422918">"SIM картны PUK-түгжигдсэн. Тайлах бол PUK кодыг бичнэ үү."</string> - <string name="needPuk2" msgid="7032612093451537186">"SIM картын хаалтыг болиулах бол PUK2-г бичнэ үү."</string> + <string name="needPuk2" msgid="7032612093451537186">"SIM картыг блокоос гаргах бол PUK2-г бичнэ үү."</string> <string name="enablePin" msgid="2543771964137091212">"Амжилтгүй боллоо, СИМ/РҮИМ түгжээг идэвхжүүлнэ үү."</string> <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584"> <item quantity="other">Таны СИМ түгжигдэхээс өмнө танд <xliff:g id="NUMBER_1">%d</xliff:g> оролдлого хийх боломж үлдлээ. </item> @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS үйлчилгээ"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Мэдрэгчийн мэдэгдлийн үйлчилгээ"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight үйлчилгээ"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Цагийн бүс илрүүлэгч (Холболт байхгүй)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Таны төхөөрөмж устах болно."</string> <string name="factory_reset_message" msgid="2657049595153992213">"Админ аппыг ашиглах боломжгүй. Таны төхөөрөмжийг одоо устгана.\n\nХэрэв танд асуулт байгаа бол байгууллагынхаа админтай холбогдоно уу."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> хэвлэх үйлдлийг идэвхгүй болгосон."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB холболт"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Апп ажиллаж байна"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апп батарей ашиглаж байна"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Томруулах"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> батерей ашиглаж байна"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> апп батерей ашиглаж байна"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батерей, дата ашиглалтын талаар дэлгэрэнгүйг харахын тулд товшино уу"</string> @@ -480,10 +480,10 @@ <string name="permdesc_transmitIr" product="tablet" msgid="5884738958581810253">"Апп-д таблетын хэт улаан дамжуулагчийг ашиглахыг зөвшөөрнө."</string> <string name="permdesc_transmitIr" product="tv" msgid="3278506969529173281">"Аппад таны Android TV төхөөрөмжийн хэт улаан туяаны дамжуулагчийг ашиглахыг зөвшөөрнө."</string> <string name="permdesc_transmitIr" product="default" msgid="8484193849295581808">"Апп-д утасны хэт улаан дамжуулагчийг ашиглахыг зөвшөөрнө."</string> - <string name="permlab_setWallpaper" msgid="6959514622698794511">"ханын зургийг тохируулах"</string> - <string name="permdesc_setWallpaper" msgid="2973996714129021397">"Апп нь системийн ханын зургийг тохируулах боломжтой."</string> - <string name="permlab_setWallpaperHints" msgid="1153485176642032714">"Таны ханын зурагны хэмжээг тохируулах"</string> - <string name="permdesc_setWallpaperHints" msgid="6257053376990044668">"Апп нь системийн ханын зургийн хэмжээний саналыг тохируулах боломжтой"</string> + <string name="permlab_setWallpaper" msgid="6959514622698794511">"дэлгэцийн зургийг тохируулах"</string> + <string name="permdesc_setWallpaper" msgid="2973996714129021397">"Апп нь системийн дэлгэцийн зургийг тохируулах боломжтой."</string> + <string name="permlab_setWallpaperHints" msgid="1153485176642032714">"Таны дэлгэцийн зургийн хэмжээг тохируулах"</string> + <string name="permdesc_setWallpaperHints" msgid="6257053376990044668">"Апп нь системийн дэлгэцийн зургийн хэмжээний саналыг тохируулах боломжтой"</string> <string name="permlab_setTimeZone" msgid="7922618798611542432">"цагийн бүсийн тохиргоо"</string> <string name="permdesc_setTimeZone" product="tablet" msgid="1788868809638682503">"Апп нь таблетын цагийн бүсийг солих боломжтой."</string> <string name="permdesc_setTimeZone" product="tv" msgid="9069045914174455938">"Аппад таны Android TV төхөөрөмжийн цагийн бүсийг өөрчлөхийг зөвшөөрнө."</string> @@ -1429,8 +1429,8 @@ <string name="input_method_binding_label" msgid="1166731601721983656">"Оруулах арга"</string> <string name="sync_binding_label" msgid="469249309424662147">"Синк"</string> <string name="accessibility_binding_label" msgid="1974602776545801715">"Хандалт"</string> - <string name="wallpaper_binding_label" msgid="1197440498000786738">"Ханын зураг"</string> - <string name="chooser_wallpaper" msgid="3082405680079923708">"Ханын зураг солих"</string> + <string name="wallpaper_binding_label" msgid="1197440498000786738">"Дэлгэцийн зураг"</string> + <string name="chooser_wallpaper" msgid="3082405680079923708">"Дэлгэцийн зураг солих"</string> <string name="notification_listener_binding_label" msgid="2702165274471499713">"Мэдэгдэл сонсогч"</string> <string name="vr_listener_binding_label" msgid="8013112996671206429">"VR сонсогч"</string> <string name="condition_provider_service_binding_label" msgid="8490641013951857673">"Нөхцөл нийлүүлэгч"</string> @@ -1510,7 +1510,7 @@ <string name="shareactionprovider_share_with_application" msgid="4902832247173666973">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>-тай хуваалцана уу"</string> <string name="content_description_sliding_handle" msgid="982510275422590757">"Бариулыг гулсуулна. Хүрээд хүлээнэ."</string> <string name="description_target_unlock_tablet" msgid="7431571180065859551">"Түгжээг тайлах бол татна уу"</string> - <string name="action_bar_home_description" msgid="1501655419158631974">"Нүүр хуудасруу шилжих"</string> + <string name="action_bar_home_description" msgid="1501655419158631974">"Нүүр хуудас руу шилжих"</string> <string name="action_bar_up_description" msgid="6611579697195026932">"Дээш шилжих"</string> <string name="action_menu_overflow_description" msgid="4579536843510088170">"Нэмэлт сонголтууд"</string> <string name="action_bar_home_description_format" msgid="5087107531331621803">"%1$s, %2$s"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Шинэ: Цонх томруулагч"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Та одоо зарим эсвэл бүх дэлгэцээ томруулж болно"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Тохиргоонд асаана уу"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Үл хэрэгсэх"</string> </resources> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index 058863389c75..7a8fd1ae2ff6 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS सेवा"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"सेन्सर सूचना सेवा"</string> <string name="twilight_service" msgid="8964898045693187224">"ट्वायलाइट सेवा"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"टाइम झोन डिटेक्टर (कनेक्टिव्हिटी नाही)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"तुमचे डिव्हाइस मिटविले जाईल"</string> <string name="factory_reset_message" msgid="2657049595153992213">"प्रशासक अॅप वापरता येणार नाही. तुमचे डिव्हाइस आता साफ केले जाईल.\n\nतुम्हाला कुठलेही प्रश्न असल्यास, तुमच्या संस्थेच्या प्रशासकाशी संपर्क साधा."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> नी प्रिंट करणे बंद केले आहे."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB कनेक्शन"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"APP चालत आहे"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"बॅटरी लवकर संपवणारी अॅप्स"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"मॅग्निफिकेशन"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> बॅटरी वापरत आहे"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> अॅप्स बॅटरी वापरत आहेत"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"बॅटरी आणि डेटा वापराच्या तपशीलांसाठी टॅप करा"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"नवीन: विंडो मॅग्निफायर"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"आता स्क्रीन अंशतः किंवा पूर्ण मॅग्निफाय करू शकता"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"सेटिंग्ज मध्ये सुरू करा"</string> + <string name="dismiss_action" msgid="1728820550388704784">"डिसमिस करा"</string> </resources> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index 1d70f76f3cd7..e94dcdea2f13 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Perkhidmatan GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Perkhidmatan Pemberitahuan Penderia"</string> <string name="twilight_service" msgid="8964898045693187224">"Perkhidmatan Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Pengesan Zon Waktu (Tiada kesambungan)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Peranti anda akan dipadam"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Apl pentadbir tidak dapat digunakan. Peranti anda akan dipadamkan sekarang.\n\nJika anda ingin mengemukakan soalan, hubungi pentadbir organisasi anda."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Pencetakan dilumpuhkan oleh <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Sambungan USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Apl berjalan"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apl yang menggunakan bateri"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Pembesaran"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang menggunakan bateri"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apl sedang menggunakan bateri"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ketik untuk mendapatkan butiran tentang penggunaan kuasa bateri dan data"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Baharu: Pembesar Tetingkap"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Besarkan sebahagian atau keseluruhan skrin anda"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Hidupkan dalam Tetapan"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Tolak"</string> </resources> diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index 097c6c599e2b..c31b7b24c186 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS ဝန်ဆောင်မှု"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"အာရုံခံကိရိယာ အကြောင်းကြားချက် ဝန်ဆောင်မှု"</string> <string name="twilight_service" msgid="8964898045693187224">"နေဝင်ဆည်းဆာ ဝန်ဆောင်မှု"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ဒေသစံတော်ချိန် ရှာဖွေစနစ် (ချိတ်ဆက်နိုင်မှု မလိုပါ)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"သင့်ကိရိယာအား ပယ်ဖျက်လိမ့်မည်"</string> <string name="factory_reset_message" msgid="2657049595153992213">"စီမံခန့်ခွဲမှု အက်ပ်ကို သုံး၍မရပါ။ သင်၏ စက်ပစ္စည်းအတွင်းရှိ အရာများကို ဖျက်လိုက်ပါမည်\n\nမေးစရာများရှိပါက သင့်အဖွဲ့အစည်း၏ စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ။"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> က ပုံနှိပ်ထုတ်ယူခြင်းကို ပိတ်ထားသည်။"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB ချိတ်ဆက်မှု"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"APP လုပ်ဆောင်နေသည်"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"အက်ပ်များက ဘက်ထရီကုန်စေသည်"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ချဲ့ခြင်း"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> က ဘက်ထရီကို အသုံးပြုနေသည်"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"အက်ပ် <xliff:g id="NUMBER">%1$d</xliff:g> ခုက ဘက်ထရီကို အသုံးပြုနေသည်"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ဘက်ထရီနှင့် ဒေတာအသုံးပြုမှု အသေးစိတ်ကို ကြည့်ရန် တို့ပါ"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"အသစ်- ဝင်းဒိုးမှန်ဘီလူး"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ဖန်သားပြင် တစ်စိတ်တစ်ပိုင်း (သို့) တစ်ခုလုံး ချဲ့နိုင်ပါပြီ"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"\'ဆက်တင်များ\' တွင် ဖွင့်ရန်"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ပယ်ရန်"</string> </resources> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 6fa80dd10722..7f2c6aaa82c0 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-tjeneste"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tidssoneoppdagelse (ingen tilkobling)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Enheten blir slettet"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Administratorappen kan ikke brukes. Enheten din blir nå tømt.\n\nTa kontakt med administratoren for organisasjonen din hvis du har spørsmål."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> har slått av utskrift."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-tilkobling"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App kjører"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apper bruker batteri"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Forstørring"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruker batteri"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apper bruker batteri"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Trykk for detaljer om batteri- og databruk"</string> @@ -1800,8 +1800,8 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"Oppdatert av administratoren din"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"Slettet av administratoren din"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"For å forlenge batterilevetiden gjør Batterisparing dette:\n\n• Slår på mørkt tema\n• Slår av eller begrenser bakgrunnsaktivitet, enkelte visuelle effekter og andre funksjoner, for eksempel «Hey Google»\n\n"<annotation id="url">"Finn ut mer"</annotation></string> - <string name="battery_saver_description" msgid="6794188153647295212">"For å forlenge batterilevetiden gjør Batterisparing dette:\n\n• Slår på mørkt tema\n• Slår av eller begrenser bakgrunnsaktivitet, enkelte visuelle effekter og andre funksjoner, for eksempel «Hey Google»"</string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"For å forlenge batterilevetiden gjør Batterisparing dette:\n\n• slår på mørkt tema\n• slår av eller begrenser bakgrunnsaktivitet, enkelte visuelle effekter og andre funksjoner, for eksempel «Hey Google»\n\n"<annotation id="url">"Finn ut mer"</annotation></string> + <string name="battery_saver_description" msgid="6794188153647295212">"For å forlenge batterilevetiden gjør Batterisparing dette:\n\n• slår på mørkt tema\n• slår av eller begrenser bakgrunnsaktivitet, enkelte visuelle effekter og andre funksjoner, for eksempel «Hey Google»"</string> <string name="data_saver_description" msgid="4995164271550590517">"Datasparing hindrer noen apper fra å sende og motta data i bakgrunnen, for å redusere dataforbruket. Aktive apper kan bruke data, men kanskje ikke så mye som ellers – for eksempel vises ikke bilder før du trykker på dem."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Vil du slå på Datasparing?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Slå på"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nytt: vindusforstørrer"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Nå kan du forstørre deler av eller hele skjermen"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Slå på i innstillingene"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Avvis"</string> </resources> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 28c35254c5db..d555b7cae2e3 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS सेवा"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"सेन्सरको सूचनासम्बन्धी सेवा"</string> <string name="twilight_service" msgid="8964898045693187224">"ट्वाइलाइट सेवा"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"समय क्षेत्र पत्ता लगाउने सुविधा (नेटवर्क कनेक्सन नहुँदा)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"तपाईंको यन्त्र मेटिनेछ"</string> <string name="factory_reset_message" msgid="2657049595153992213">"प्रशासकको एप प्रयोग गर्न मिल्दैन। तपाईंको यन्त्रको डेटा अब मेटाइने छ।\n\nतपाईंसँग प्रश्नहरू भएका खण्डमा आफ्नो संगठनका प्रशासकसँग सम्पर्क गर्नुहोस्।"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ले छाप्ने कार्यलाई असक्षम पार्यो।"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB जडान"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"एप चलिरहेको छ"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"एपहरूले ब्याट्री खपत गर्दै छन्"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"जुम इन गर्ने सुविधा"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ले ब्याट्री प्रयोग गर्दै छ"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> एपहरूले ब्याट्री प्रयोग गर्दै छन्"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ब्याट्री र डेटाका प्रयोग सम्बन्धी विवरणहरूका लागि ट्याप गर्नुहोस्"</string> @@ -1965,7 +1965,7 @@ <string name="autofill_save_type_debit_card" msgid="3169397504133097468">"डेबिट कार्ड"</string> <string name="autofill_save_type_payment_card" msgid="6555012156728690856">"भुक्तानी कार्ड"</string> <string name="autofill_save_type_generic_card" msgid="1019367283921448608">"कार्ड"</string> - <string name="autofill_save_type_username" msgid="1018816929884640882">"प्रयोगकर्ताको नाम"</string> + <string name="autofill_save_type_username" msgid="1018816929884640882">"युजरनेम"</string> <string name="autofill_save_type_email_address" msgid="1303262336895591924">"इमेल ठेगाना"</string> <string name="etws_primary_default_message_earthquake" msgid="8401079517718280669">"शान्त रहनुहोस् र नजिकै आश्रयस्थल खोज्नुहोस्।"</string> <string name="etws_primary_default_message_tsunami" msgid="5828171463387976279">"तटीय क्षेत्र र नदीछेउका ठाउँहरू छाडी उच्च सतहमा अवस्थित कुनै अझ सुरक्षित ठाउँमा जानुहोस्।"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"नयाँ सुविधा: विन्डो म्याग्निफायर"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"तपाईं अब स्क्रिनको केही वा सबै भाग जुम इन गर्न सक्नुहुन्छ"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"सेटिङमा गई यो सुविधा अन गर्नुहोस्"</string> + <string name="dismiss_action" msgid="1728820550388704784">"हटाउनुहोस्"</string> </resources> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 8b571e82dea8..04f598d61aff 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-service"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Service voor sensormeldingen"</string> <string name="twilight_service" msgid="8964898045693187224">"Service voor schemering"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tijdzonedetector (Geen verbinding)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Je apparaat wordt gewist"</string> <string name="factory_reset_message" msgid="2657049595153992213">"De beheer-app kan niet worden gebruikt. Je apparaat wordt nu gewist.\n\nNeem contact op met de beheerder van je organisatie als je vragen hebt."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Afdrukken uitgeschakeld door <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-verbinding"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App actief"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps die de batterij gebruiken"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Vergroting"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruikt de batterij"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps gebruiken de batterij"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tik voor batterij- en datagebruik"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nieuw: Venstervergroting"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Je kunt je scherm nu (gedeeltelijk) vergroten"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Inschakelen in Instellingen"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Sluiten"</string> </resources> diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index 4b5c9b0be420..bccb824609e2 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS ସର୍ଭିସ୍"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"ସେନ୍ସର୍ ନୋଟିଫିକେସନ୍ ସର୍ଭିସ୍"</string> <string name="twilight_service" msgid="8964898045693187224">"ଟ୍ୱିଲାଇଟ୍ ସର୍ଭିସ୍"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ଟାଇମ୍ ଜୋନ୍ ଡିଟେକ୍ଟର୍ (କୌଣସି ସଂଯୋଗ ନାହିଁ)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"ଆପଣଙ୍କ ଡିଭାଇସ୍ ବର୍ତ୍ତମାନ ଲିଭାଯିବ"</string> <string name="factory_reset_message" msgid="2657049595153992213">"ଆଡମିନ୍ ଆପ୍ ବ୍ୟବହାର କରାଯାଇପାରିବ ନାହିଁ। ଆପଣଙ୍କ ଡିଭାଇସ୍ର ସମସ୍ତ ଡାଟାକୁ ବର୍ତ୍ତମାନ ଲିଭାଇଦିଆଯିବ। \n\nଯଦି ଆପଣଙ୍କର କୌଣସି ପ୍ରଶ୍ନ ରହିଥାଏ, ଆପଣଙ୍କ ସଂସ୍ଥାର ଆଡମିନ୍ଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ଦ୍ଵାରା ପ୍ରିଣ୍ଟିଙ୍ଗ ଅକ୍ଷମ କରାଯାଇଛି"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB ସଂଯୋଗ"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ଆପ୍ ଚାଲୁଛି"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ଆପ୍ଗୁଡ଼ିକ ବ୍ୟାଟେରୀ ଖର୍ଚ୍ଚ କରିଥା\'ନ୍ତି"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ମ୍ୟାଗ୍ନିଫିକେସନ୍"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରୁଛି"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>ଟି ଆପ୍ ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରୁଛନ୍ତି"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ବ୍ୟାଟେରୀ ଏବଂ ଡାଟା ବ୍ୟବହାର ଉପରେ ବିବରଣୀ ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ନୂଆ: ୱିଣ୍ଡୋ ମ୍ୟାଗ୍ନିଫାୟର୍"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ଆପଣ ଏବେ ଆଂଶିକ ବା ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ୍ ବଡ଼ କରିପାରିବେ"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ସେଟିଂସରେ ଚାଲୁ କରନ୍ତୁ"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ଖାରଜ କରନ୍ତୁ"</string> </resources> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 5de08850a3ee..2d16de8a3cee 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS ਸੇਵਾ"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"ਸੈਂਸਰ ਸੂਚਨਾ ਸੇਵਾ"</string> <string name="twilight_service" msgid="8964898045693187224">"ਟਵੀਲਾਈਟ ਸੇਵਾ"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ਸਮਾਂ ਖੇਤਰ ਦਾ ਪਤਾ ਲਗਾਉਣ ਦੀ ਸੁਵਿਧਾ (ਕੋਈ ਕਨੈਕਟੀਵਿਟੀ ਨਹੀਂ)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਮਿਟਾਇਆ ਜਾਏਗਾ"</string> <string name="factory_reset_message" msgid="2657049595153992213">"ਪ੍ਰਸ਼ਾਸਕ ਐਪ ਵਰਤੀ ਨਹੀਂ ਜਾ ਸਕਦੀ। ਹੁਣ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦਾ ਡਾਟਾ ਮਿਟਾਇਆ ਜਾਵੇਗਾ।\n\nਜੇਕਰ ਤੁਹਾਡੇ ਕੋਲ ਕੋਈ ਸਵਾਲ ਹਨ, ਤਾਂ ਆਪਣੀ ਸੰਸਥਾ ਦੇ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ਵੱਲੋਂ ਪ੍ਰਿੰਟ ਕਰਨਾ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB ਕਨੈਕਸ਼ਨ"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ਚੱਲ ਰਹੀ ਐਪ"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ਬੈਟਰੀ ਦੀ ਖਪਤ ਕਰਨ ਵਾਲੀਆਂ ਐਪਾਂ"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ਵੱਡਦਰਸ਼ੀਕਰਨ"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਵੱਲੋਂ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ਐਪਾਂ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀਆਂ ਹਨ"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ਬੈਟਰੀ ਅਤੇ ਡਾਟਾ ਵਰਤੋਂ ਸਬੰਧੀ ਵੇਰਵਿਆਂ ਲਈ ਟੈਪ ਕਰੋ"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ਨਵਾਂ: Window ਵੱਡਦਰਸ਼ੀ"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ਹੁਣ ਤੁਸੀਂ ਕੁਝ ਜਾਂ ਪੂਰੀ ਸਕ੍ਰੀਨ ਵੱਡਦਰਸ਼ੀ ਕਰ ਸਕਦੇ ਹੋ"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਚਾਲੂ ਕਰੋ"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ਖਾਰਜ ਕਰੋ"</string> </resources> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 427beb508366..95343591abc8 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Usługa GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Usługa powiadomień czujnika"</string> <string name="twilight_service" msgid="8964898045693187224">"Usługa Zmierzch"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Wykrywanie strefy czasowej (brak połączenia)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Twoje urządzenie zostanie wyczyszczone"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Nie można użyć aplikacji administratora. Dane z urządzenia zostaną wykasowane.\n\nJeśli masz pytania, skontaktuj się z administratorem organizacji."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Drukowanie wyłączone przez: <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Połączenie USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Działa aplikacja"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacje zużywające baterię"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Powiększenie"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> zużywa baterię"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Liczba aplikacji zużywających baterię: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Kliknij, by wyświetlić szczegóły wykorzystania baterii i użycia danych"</string> @@ -1846,7 +1846,7 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"Zaktualizowany przez administratora"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"Usunięty przez administratora"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Aby wydłużyć czas pracy na baterii, funkcja Oszczędzanie baterii:\n\n•włącza tryb ciemny,\n• wyłącza lub ogranicza aktywność w tle, niektóre efekty wizualne oraz inne funkcje, np. „OK Google”.\n\n"<annotation id="url">"Więcej informacji"</annotation></string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Aby wydłużyć czas pracy na baterii, funkcja Oszczędzanie baterii:\n\n• włącza tryb ciemny,\n• wyłącza lub ogranicza aktywność w tle, niektóre efekty wizualne oraz inne funkcje, np. „OK Google”.\n\n"<annotation id="url">"Więcej informacji"</annotation></string> <string name="battery_saver_description" msgid="6794188153647295212">"Aby wydłużyć czas pracy na baterii, Oszczędzanie baterii:\n\n• włącza tryb ciemny,\n• wyłącza lub ogranicza aktywność w tle, niektóre efekty wizualne oraz inne funkcje, np. „OK Google”."</string> <string name="data_saver_description" msgid="4995164271550590517">"Oszczędzanie danych uniemożliwia niektórym aplikacjom wysyłanie i odbieranie danych w tle, zmniejszając w ten sposób ich użycie. Aplikacja, z której w tej chwili korzystasz, może uzyskiwać dostęp do danych, ale rzadziej. Może to powodować, że obrazy będą się wyświetlać dopiero po kliknięciu."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Włączyć Oszczędzanie danych?"</string> @@ -2258,12 +2258,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nowość: powiększanie okna"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Możesz teraz powiększyć część lub całość ekranu"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Włącz w Ustawieniach"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Odrzuć"</string> </resources> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index 3fed0287bc1e..8198a62fcda0 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Serviço de GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Serviço de notificações do sensor"</string> <string name="twilight_service" msgid="8964898045693187224">"Serviço de crepúsculo"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de fuso horário (sem conectividade)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Seu dispositivo será limpo"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Não é possível usar o aplicativo para administrador. Seu dispositivo passará por uma limpeza agora.\n\nEm caso de dúvidas, entre em contato com o administrador da sua organização."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Impressão desativada por <xliff:g id="OWNER_APP">%s</xliff:g>."</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 1c890dd4b651..71dd2b9bfafe 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Serviço GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Serviço de notificações do sensor"</string> <string name="twilight_service" msgid="8964898045693187224">"Serviço de crepúsculo"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detetor do fuso horário (sem conetividade)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"O seu dispositivo será apagado"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Não é possível utilizar a app de administrador. O seu dispositivo será agora apagado.\n\nSe tiver questões, contacte o administrador da entidade."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Impressão desativada por <xliff:g id="OWNER_APP">%s</xliff:g>."</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 3fed0287bc1e..8198a62fcda0 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Serviço de GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Serviço de notificações do sensor"</string> <string name="twilight_service" msgid="8964898045693187224">"Serviço de crepúsculo"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de fuso horário (sem conectividade)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Seu dispositivo será limpo"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Não é possível usar o aplicativo para administrador. Seu dispositivo passará por uma limpeza agora.\n\nEm caso de dúvidas, entre em contato com o administrador da sua organização."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Impressão desativada por <xliff:g id="OWNER_APP">%s</xliff:g>."</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 5cf30763d8f0..4d091e915f93 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -201,6 +201,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Serviciul GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Serviciu pentru notificări de la senzori"</string> <string name="twilight_service" msgid="8964898045693187224">"Serviciul Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de fus orar (fără conexiune)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Datele de pe dispozitiv vor fi șterse"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Aplicația de administrare nu poate fi utilizată. Dispozitivul va fi șters.\n\nDacă aveți întrebări, contactați administratorul organizației dvs."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Printare dezactivată de <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -290,8 +291,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Conexiune USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplicația rulează"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicațiile consumă bateria"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Mărire"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> folosește bateria"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicații folosesc bateria"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Atingeți pentru mai multe detalii privind bateria și utilizarea datelor"</string> @@ -2224,12 +2224,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nou: lupă fereastră"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Acum puteți mări o parte sau tot ecranul"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activați din Setări"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Respingeți"</string> </resources> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index efd3c6c5ad96..783ec9a399e9 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Служба GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Сервис для обработки уведомлений от датчиков"</string> <string name="twilight_service" msgid="8964898045693187224">"Сервис для определения наступления сумерек"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Определитель часового пояса (работает без Интернета)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Все данные с устройства будут удалены"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Невозможно использовать приложение для администрирования. С устройства будут удалены все данные.\n\nЕсли у вас возникли вопросы, обратитесь к администратору."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Функция печати отключена приложением \"<xliff:g id="OWNER_APP">%s</xliff:g>\""</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-подключение"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Приложение активно"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Приложения, расходующие заряд"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Увеличение"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" расходует заряд"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Несколько приложений (<xliff:g id="NUMBER">%1$d</xliff:g>) расходуют заряд"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Нажмите, чтобы проверить энергопотребление и трафик"</string> @@ -2258,12 +2258,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Новинка: экранная лупа"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Теперь можно увеличивать весь экран или его часть."</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Включить в настройках"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Закрыть"</string> </resources> diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index 100aed1c3c66..74b400802034 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS සේවාව"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"සංවේදක දැනුම් දීමේ සේවාව"</string> <string name="twilight_service" msgid="8964898045693187224">"ඇඳිරි සේවාව"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"වේලා කලාප අනාවරකය (සම්බන්ධතාවක් නොමැත)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"ඔබගේ උපාංගය මකා දැමෙනු ඇත"</string> <string name="factory_reset_message" msgid="2657049595153992213">"පරිපාලක යෙදුම භාවිතා කළ නොහැකිය. ඔබේ උපාංගය දැන් මකා දමනු ඇත.\n\nඔබට ප්රශ්න තිබේ නම්, ඔබේ සංවිධානයේ පරිපාලකට අමතන්න."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> විසින් මුද්රණය කිරීම අබල කර ඇත."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB සම්බන්ධතාවය"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"යෙදුම ධාවනය කරමින්"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"බැටරිය භාවිත කරන යෙදුම්"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"විශාලනය"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> බැටරිය භාවිත කරයි"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"යෙදුම් <xliff:g id="NUMBER">%1$d</xliff:g>ක් බැටරිය භාවිත කරයි"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"බැටරි හා දත්ත භාවිතය පිළිබඳව විස්තර සඳහා තට්ටු කරන්න"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"නව: කවුළු විශාලකය"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ඔබට දැන් තිරයේ සමහර හෝ සියලු දේ විශාලනය කළ හැකිය"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"සැකසීම් තුළ ක්රියාත්මක කරන්න"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ඉවත ලන්න"</string> </resources> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index f7756e5959ce..74e2b692ad9a 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Služba GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Služba upozornení senzora"</string> <string name="twilight_service" msgid="8964898045693187224">"Služba stmievania"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detektor časového pásma (bez pripojenia)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Vaše zariadenie bude vymazané"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Daná aplikácia na správu sa nedá použiť. Vaše zariadenie bude vymazané.\n\nV prípade otázok kontaktujte správcu organizácie."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Tlač zakázala aplikácia <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Pripojenie USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikácia je spustená"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikácie spotrebúvajúce batériu"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Zväčšenie"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> používa batériu"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikácie (<xliff:g id="NUMBER">%1$d</xliff:g>) používajú batériu"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Klepnutím zobrazíte podrobnosti o batérii a spotrebe dát"</string> @@ -2258,12 +2258,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novinka: Lupa pre okná"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Teraz môžete zväčšiť celú obrazovku alebo jej časť"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Zapnúť v Nastaveniach"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Zavrieť"</string> </resources> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index df7e0ee1a856..755db5c0e6a4 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Storitev GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Storitev obvestil tipal"</string> <string name="twilight_service" msgid="8964898045693187224">"Storitev Somrak"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Zaznavanje časovnega pasu (brez povezave)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Podatki v napravi bodo izbrisani"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Skrbniške aplikacije ni mogoče uporabljati. Podatki v napravi bodo izbrisani.\n\nČe imate vprašanja, se obrnite na skrbnika organizacije."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Tiskanje je onemogočil pravilnik <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Povezava USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikacija se izvaja"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije, ki porabljajo energijo baterije"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Povečava"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> porablja energijo baterije"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Toliko aplikacij porablja energijo baterije: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dotaknite se za prikaz podrobnosti porabe baterije in prenosa podatkov"</string> @@ -1846,7 +1846,7 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"Posodobil skrbnik"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisal skrbnik"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"V redu"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Funkcija varčevanja z energijo baterije podaljša čas delovanja baterije tako:\n\n•vklopi temno temo,\n•izklopi ali omeji dejavnost v ozadju, nekatere vizualne učinke in druge funkcije, kot je »Hey Google«.\n\n"<annotation id="url">"Več o tem"</annotation></string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Funkcija varčevanja z energijo baterije podaljša čas delovanja baterije tako:\n\n• vklopi temno temo,\n• izklopi ali omeji dejavnost v ozadju, nekatere vizualne učinke in druge funkcije, kot je »Hey Google«.\n\n"<annotation id="url">"Več o tem"</annotation></string> <string name="battery_saver_description" msgid="6794188153647295212">"Funkcija varčevanja z energijo baterije podaljša čas delovanja baterije tako:\n\n• vklopi temno temo;\n• izklopi ali omeji dejavnost v ozadju, nekatere vizualne učinke in druge funkcije, kot je »Hey Google«."</string> <string name="data_saver_description" msgid="4995164271550590517">"Zaradi zmanjševanja prenesene količine podatkov funkcija varčevanja s podatki nekaterim aplikacijam preprečuje, da bi v ozadju pošiljale ali prejemale podatke. Aplikacija, ki jo trenutno uporabljate, lahko prenaša podatke, vendar to morda počne manj pogosto. To na primer pomeni, da se slike ne prikažejo, dokler se jih ne dotaknete."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Vklop varčevanja s podatki?"</string> @@ -2258,12 +2258,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novo: Lupa v oknu"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Zdaj lahko povečate del zaslona ali celotni zaslon"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Vklopite v nastavitvah"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Opusti"</string> </resources> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index 8de3f8ca4f80..bd970a092874 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Shërbimi GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Shërbimi i njoftimeve të sensorit"</string> <string name="twilight_service" msgid="8964898045693187224">"Shërbimi i muzgut"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Zbuluesi i brezit orar (nuk nevojitet lidhja)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Pajisja do të spastrohet"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Aplikacioni i administratorit nuk mund të përdoret. Pajisja jote tani do të fshihet.\n\nNëse ke pyetje, kontakto me administratorin e organizatës."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Printimi është çaktivizuar nga <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Lidhja USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikacioni është në ekzekutim"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacionet që konsumojnë baterinë"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Zmadhimi"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> po përdor baterinë"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikacione po përdorin baterinë"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Trokit për detaje mbi baterinë dhe përdorimin e të dhënave"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Risi: Zmadhuesi i dritareve"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Tani mund t\'i zmadhosh një pjesë apo të gjithë ekranin tënd"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktivizo te \"Cilësimet\""</string> + <string name="dismiss_action" msgid="1728820550388704784">"Hiq"</string> </resources> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index e4031189f26e..a3acb3d48717 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -201,6 +201,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS услуга"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Услуга обавештења сензора"</string> <string name="twilight_service" msgid="8964898045693187224">"Услуга Сумрак"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Детектор временске зоне (нема интернет везе)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Уређај ће бити обрисан"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Не можете да користите ову апликацију за администраторе. Уређај ће сада бити обрисан.\n\nАко имате питања, контактирајте администратора организације."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Штампање је онемогућила апликација <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -290,8 +291,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB веза"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Активна апликација"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апликације које троше батерију"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Увећање"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> користи батерију"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Апликације (<xliff:g id="NUMBER">%1$d</xliff:g>) користе батерију"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Додирните за детаље о батерији и потрошњи података"</string> @@ -932,7 +932,7 @@ <string name="granularity_label_link" msgid="9007852307112046526">"линк"</string> <string name="granularity_label_line" msgid="376204904280620221">"ред"</string> <string name="factorytest_failed" msgid="3190979160945298006">"Фабричко тестирање није успело"</string> - <string name="factorytest_not_system" msgid="5658160199925519869">"Радња FACTORY_TEST је подржана само за пакете инсталиране у директоријуму /system/app."</string> + <string name="factorytest_not_system" msgid="5658160199925519869">"Радња FACTORY_TEST је подржана само за пакете инсталиране у фолдеру /system/app."</string> <string name="factorytest_no_action" msgid="339252838115675515">"Није пронађен ниједан пакет који обезбеђује радњу FACTORY_TEST."</string> <string name="factorytest_reboot" msgid="2050147445567257365">"Рестартуј"</string> <string name="js_dialog_title" msgid="7464775045615023241">"На страници на адреси „<xliff:g id="TITLE">%s</xliff:g>“ пише:"</string> @@ -2048,7 +2048,7 @@ <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Батерија телефона је довољно напуњена. Функције више нису ограничене."</string> <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Батерија таблета је довољно напуњена. Функције више нису ограничене."</string> <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Батерија уређаја је довољно напуњена. Функције више нису ограничене."</string> - <string name="mime_type_folder" msgid="2203536499348787650">"Директоријум"</string> + <string name="mime_type_folder" msgid="2203536499348787650">"Фолдер"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android апликација"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Датотека"</string> <string name="mime_type_generic_ext" msgid="9220220924380909486">"<xliff:g id="EXTENSION">%1$s</xliff:g> датотека"</string> @@ -2224,12 +2224,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Ново: Лупа за прозор"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Можете да увећате део екрана или цео екран"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Укључите у Подешавањима"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Одбаци"</string> </resources> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index cc21f3929356..ddd3faa4a051 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-tjänst"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tidszondetektering (ingen anslutning)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Enheten kommer att rensas"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Det går inte att använda administratörsappen. Enheten rensas.\n\nKontakta organisationens administratör om du har några frågor."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Utskrift har inaktiverats av <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-anslutning"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App körs"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Appar som drar batteri"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Förstoring"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> drar batteri"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> appar drar batteri"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tryck för information om batteri- och dataanvändning"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nyhet: Fönsterförstoring"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Nu kan du förstora delar av eller hela skärmen"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktivera i inställningarna"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Stäng"</string> </resources> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 9478b0b50832..62b1c0617cad 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Huduma ya GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Huduma ya Arifa ya Kitambuzi"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Kitambua Saa za Eneo (Hakuna muunganisho)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Data iliyomo kwenye kifaa chako itafutwa"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Huwezi kutumia programu ya msimamizi. Sasa data iliyo kwenye kifaa chako itafutwa.\n\nIkiwa una maswali yoyote, wasiliana na msimamizi wa shirika lako."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Kipengele cha kuchapisha kimezimwa na <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Muunganisho wa USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Programu inaendelea kutekelezwa"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programu zinazotumia betri"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ukuzaji"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> inatumia betri"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Programu <xliff:g id="NUMBER">%1$d</xliff:g> zinatumia betri"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Gusa ili upate maelezo kuhusu betri na matumizi ya data"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Mpya: Kikuza Dirisha"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Sasa unaweza kukuza sehemu ya au skrini yako yote"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Washa katika Mipangilio"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Ondoa"</string> </resources> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index ebaeaddfd86f..28a9cb7b26c4 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS சேவை"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"சென்சார் அறிவிப்புச் சேவை"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight சேவை"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"நேர மண்டல டிடெக்டர் (இணைப்பு இல்லை)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"சாதனத் தரவு அழிக்கப்படும்"</string> <string name="factory_reset_message" msgid="2657049595153992213">"நிர்வாகி ஆப்ஸை உபயோகிக்க முடியாது. இப்போது, உங்கள் சாதனம் ஆரம்ப நிலைக்கு மீட்டமைக்கப்படும்.\n\nஏதேனும் கேள்விகள் இருப்பின், உங்கள் நிறுவனத்தின் நிர்வாகியைத் தொடர்புகொள்ளவும்."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"பிரிண்ட் செய்வதை <xliff:g id="OWNER_APP">%s</xliff:g> தடுத்துள்ளது."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB இணைப்பு"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ஆப்ஸ் இயங்குகிறது"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"பேட்டரியைப் பயன்படுத்தும் ஆப்ஸ்"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"பெரிதாக்கல்"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் பேட்டரியைப் பயன்படுத்துகிறது"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ஆப்ஸ் பேட்டரியைப் பயன்படுத்துகின்றன"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"பேட்டரி மற்றும் டேட்டா உபயோக விவரங்களைக் காண, தட்டவும்"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"புதிது: சாளரம் பெரிதாக்கும் கருவி"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"திரை முழுவதையுமோ ஒரு பகுதியையோ பெரிதாக்கலாம்"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"அமைப்புகளில் ஆன் செய்க"</string> + <string name="dismiss_action" msgid="1728820550388704784">"மூடுக"</string> </resources> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index c63d175002ea..f9e0934c15ef 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS సర్వీస్"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"సెన్సార్ నోటిఫికేషన్ సర్వీస్"</string> <string name="twilight_service" msgid="8964898045693187224">"ట్విలైట్ సర్వీస్"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"టైమ్ జోన్ డిటెక్టర్ (కనెక్టివిటీ లేదు)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"మీ పరికరంలోని డేటా తొలగించబడుతుంది"</string> <string name="factory_reset_message" msgid="2657049595153992213">"నిర్వాహక యాప్ ఉపయోగించడం సాధ్యపడదు. మీ పరికరంలోని డేటా ఇప్పుడు తొలగించబడుతుంది.\n\nమీకు ప్రశ్నలు ఉంటే, మీ సంస్థ యొక్క నిర్వాహకులను సంప్రదించండి."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"ముద్రణ <xliff:g id="OWNER_APP">%s</xliff:g> ద్వారా నిలిపివేయబడింది."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB కనెక్షన్"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"యాప్ అమలవుతోంది"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"బ్యాటరీని ఉపయోగిస్తున్న యాప్లు"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"మాగ్నిఫికేషన్"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> బ్యాటరీని ఉపయోగిస్తోంది"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> యాప్లు బ్యాటరీని ఉపయోగిస్తున్నాయి"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"బ్యాటరీ మరియు డేటా వినియోగ వివరాల కోసం నొక్కండి"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"కొత్తది: విండో మాగ్నిఫయర్"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"స్క్రీన్ మొత్తం లేదా కొంత భాగాన్ని జూమ్ చేయవచ్చు"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"సెట్టింగ్లలో ఆన్ చేయండి"</string> + <string name="dismiss_action" msgid="1728820550388704784">"విస్మరించు"</string> </resources> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index b0acb1217b8b..c23cf2b30f8d 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"บริการ GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"บริการแจ้งเตือนเกี่ยวกับเซ็นเซอร์"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ตัวตรวจจับเขตเวลา (ไม่มีการเชื่อมต่อ)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"ระบบจะลบข้อมูลในอุปกรณ์ของคุณ"</string> <string name="factory_reset_message" msgid="2657049595153992213">"ใช้แอปผู้ดูแลระบบนี้ไม่ได้ ขณะนี้ระบบจะลบข้อมูลในอุปกรณ์ของคุณ\n\nโปรดติดต่อผู้ดูแลระบบขององค์กรหากมีคำถาม"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ปิดใช้การพิมพ์แล้ว"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"การเชื่อมต่อ USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"แอปที่ทำงานอยู่"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"แอปหลายแอปกำลังใช้แบตเตอรี่"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"การขยาย"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังใช้แบตเตอรี่"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"แอป <xliff:g id="NUMBER">%1$d</xliff:g> แอปกำลังใช้แบตเตอรี่"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"แตะเพื่อดูรายละเอียดเกี่ยวกับแบตเตอรี่และปริมาณการใช้อินเทอร์เน็ต"</string> @@ -1800,7 +1800,7 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"อัปเดตโดยผู้ดูแลระบบ"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"ลบโดยผู้ดูแลระบบ"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"ตกลง"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"โหมดประหยัดแบตเตอรี่จะดำเนินการดังต่อไปนี้เพื่อยืดอายุการใช้งานแบตเตอรี่\n\n• เปิดธีมมืด\n•ปิดหรือจำกัดกิจกรรมในเบื้องหลัง เอฟเฟกต์ภาพบางอย่าง และฟีเจอร์อื่นๆ อย่างเช่น “Ok Google”\n\n"<annotation id="url">"ดูข้อมูลเพิ่มเติม"</annotation></string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"โหมดประหยัดแบตเตอรี่จะดำเนินการดังต่อไปนี้เพื่อยืดอายุการใช้งานแบตเตอรี่\n\n• เปิดธีมมืด\n• ปิดหรือจำกัดกิจกรรมในเบื้องหลัง เอฟเฟกต์ภาพบางอย่าง และฟีเจอร์อื่นๆ อย่างเช่น “Ok Google”\n\n"<annotation id="url">"ดูข้อมูลเพิ่มเติม"</annotation></string> <string name="battery_saver_description" msgid="6794188153647295212">"โหมดประหยัดแบตเตอรี่จะดำเนินการดังต่อไปนี้เพื่อยืดอายุการใช้งานแบตเตอรี่\n\n• เปิดธีมมืด\n• ปิดหรือจำกัดกิจกรรมในเบื้องหลัง เอฟเฟกต์ภาพบางอย่าง และฟีเจอร์อื่นๆ อย่างเช่น \"Ok Google\""</string> <string name="data_saver_description" msgid="4995164271550590517">"เพื่อช่วยลดปริมาณการใช้อินเทอร์เน็ต โปรแกรมประหยัดอินเทอร์เน็ตจะช่วยป้องกันไม่ให้บางแอปส่งหรือรับข้อมูลโดยการใช้อินเทอร์เน็ตอยู่เบื้องหลัง แอปที่คุณกำลังใช้งานสามารถเข้าถึงอินเทอร์เน็ตได้ แต่อาจไม่บ่อยเท่าเดิม ตัวอย่างเช่น ภาพต่างๆ จะไม่แสดงจนกว่าคุณจะแตะที่ภาพเหล่านั้น"</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"เปิดการประหยัดอินเทอร์เน็ตไหม"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ใหม่: แว่นขยายหน้าต่าง"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"คุณสามารถขยายหน้าจอบางส่วนหรือทั้งหมดได้แล้วตอนนี้"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"เปิดในการตั้งค่า"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ปิด"</string> </resources> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index f04e7e1f3d69..8a6ad7ef5716 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Serbisyo ng GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Serbisyo ng Notification ng Sensor"</string> <string name="twilight_service" msgid="8964898045693187224">"Serbisyo ng Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector ng Time Zone (Walang koneksyon)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Buburahin ang iyong device"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Hindi magamit ang admin app. Mabubura na ang iyong device.\n\nKung mayroon kang mga tanong, makipag-ugnayan sa admin ng iyong organisasyon."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Na-disable ng <xliff:g id="OWNER_APP">%s</xliff:g> ang pag-print."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Koneksyon ng USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Tumatakbo ang app"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Mga app na kumokonsumo ng baterya"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Pag-magnify"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Gumagamit ng baterya ang <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Gumagamit ng baterya ang <xliff:g id="NUMBER">%1$d</xliff:g> (na) app"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"I-tap para sa mga detalye tungkol sa paggamit ng baterya at data"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Bago: Magnifier ng Window"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Mama-magnify na ang bahagi o kabuuan ng screen mo"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"I-on sa Mga Setting"</string> + <string name="dismiss_action" msgid="1728820550388704784">"I-dismiss"</string> </resources> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 79cfe191d35f..d31d7e91f457 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS Hizmeti"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensör Bildirim Hizmeti"</string> <string name="twilight_service" msgid="8964898045693187224">"Alacakaranlık Hizmeti"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Zaman Dilimi Algılayıcı (Bağlantı yok)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Cihazınız silinecek"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Yönetim uygulaması kullanılamıyor. Cihazınız şimdi silinecek.\n\nSorularınız varsa kuruluşunuzun yöneticisine başvurun."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Yazdırma işlemi <xliff:g id="OWNER_APP">%s</xliff:g> tarafından devre dışı bırakıldı."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB bağlantısı"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Uygulama çalışıyor"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Pil kullanan uygulamalar"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Büyütme"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> pil kullanıyor"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> uygulama pil kullanıyor"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Pil ve veri kullanımı ile ilgili ayrıntılar için dokunun"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Yeni: Pencere Büyüteci"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Artık ekranınızın bir kısmını veya tamamını büyütebilirsiniz"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ayarlar\'da aç"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Kapat"</string> </resources> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index a752010655a9..2352584f95b7 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Сервіс GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Сервіс \"Сповіщення датчика\""</string> <string name="twilight_service" msgid="8964898045693187224">"Сервіс \"Сутінки\""</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Визначення часового поясу (без Інтернету)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"З вашого пристрою буде стерто всі дані"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Не можна запускати додаток для адміністраторів. Буде відновлено заводські налаштування пристрою.\n\nЯкщо у вас є запитання, зв’яжіться з адміністратором своєї організації."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Додаток <xliff:g id="OWNER_APP">%s</xliff:g> вимкнув друк."</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"З’єднання USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Працює додаток"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Додатки, що використовують заряд акумулятора"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Збільшення"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> використовує заряд акумулятора"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Додатків, що використовують заряд акумулятора: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Торкніться, щоб перевірити використання акумулятора й трафік"</string> @@ -2258,12 +2258,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Нове: збільшення вікон"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Тепер можна збільшити весь екран або його частину"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Увімкнути в налаштуваннях"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Закрити"</string> </resources> diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index 4324e36c62b9..68572d89aca0 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS سروس"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"سینسر نوٹیفکیشن سروس"</string> <string name="twilight_service" msgid="8964898045693187224">"شفقی سروس"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ٹائم زون ڈیٹیکٹر (کوئی کنیکٹوٹی نہیں ہے)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"آپ کا آلہ صاف کر دیا جائے گا"</string> <string name="factory_reset_message" msgid="2657049595153992213">"منتظم کی ایپ استعمال نہیں کی جا سکتی۔ آپ کا آلہ اب مٹا دیا جائے گا۔\n\nاگر آپ کے سوالات ہیں تو اپنی تنظیم کے منتظم سے رابطہ کریں۔"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> نے پرنٹنگ کو غیر فعال کر دیا ہے۔"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB کنکشن"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ایپ چل رہی ہے"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ایپس بیٹری خرچ کر رہی ہیں"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"میگنیفکیشن"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> بیٹری کا استعمال کر رہی ہے"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ایپس بیٹری کا استعمال کر رہی ہیں"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"بیٹری اور ڈیٹا استعمال کے بارے میں تفصیلات کے لیے تھپتھپائیں"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"نیا: ونڈو میگنیفائر"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"اب آپ اپنی تمام یا کچھ اسکرین کو بڑا کر سکتے ہیں"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ترتیبات میں آن کریں"</string> + <string name="dismiss_action" msgid="1728820550388704784">"برخاست کریں"</string> </resources> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index 923831c00b88..423669d6f48a 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS xizmati"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensorli bildirishnoma xizmati"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight xizmati"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Vaqt mintaqasini aniqlagich (Oflayn)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Qurilmangizdagi ma’lumotlar o‘chirib tashlanadi"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Administrator ilovasini ishlatib bo‘lmaydi. Qurilmada barcha ma’lumotlar o‘chirib tashlanadi.\n\nSavollaringiz bo‘lsa, administrator bilan bog‘laning."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Chop etish funksiyasi <xliff:g id="OWNER_APP">%s</xliff:g> tomonidan faolsizlantirilgan."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB orqali ulanish"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Ilova faol"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Batareya quvvatini sarflayotgan ilovalar"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Kattalashtirish"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi batareya quvvatini sarflamoqda"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ta ilova batareya quvvatini sarflamoqda"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Batareya va trafik sarfi tafsilotlari uchun ustiga bosing"</string> @@ -593,7 +593,7 @@ <string name="face_acquired_too_right" msgid="2513391513020932655">"Telefonni chapga suring."</string> <string name="face_acquired_too_left" msgid="8882499346502714350">"Telefonni oʻngga suring."</string> <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"Qurilmaga tik qarang."</string> - <string name="face_acquired_not_detected" msgid="2945945257956443257">"Telefoningizga yuzingizni tik tuting."</string> + <string name="face_acquired_not_detected" msgid="2945945257956443257">"Telefonni yuzingizga tik qarating."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Ortiqcha harakatlanmoqda. Qimirlatmasdan ushlang."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Yuzingizni qaytadan qayd qildiring."</string> <string name="face_acquired_too_different" msgid="4699657338753282542">"Yuz tanilmadi. Qaytadan urining."</string> @@ -1800,7 +1800,7 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"Administrator tomonidan yangilangan"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"Administrator tomonidan o‘chirilgan"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Batareya quvvatini uzaytirish uchun Quvvat tejash funksiyasi:\n\n• Tungi mavzuni yoqadi\n• Fondagi harakatlar, vizual effektlar va “Hey Google” kabi boshqa funksiyalarni faolsizlantiradi\n\n"<annotation id="url">"Batafsil"</annotation></string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Batareya quvvatini uzaytirish uchun Quvvat tejash funksiyasi:\n\n• Tungi mavzuni yoqadi\n• Fondagi harakatlar, vizual effektlar va “Ok Google” kabi boshqa funksiyalarni faolsizlantiradi\n\n"<annotation id="url">"Batafsil"</annotation></string> <string name="battery_saver_description" msgid="6794188153647295212">"Batareya quvvatini uzaytirish uchun Quvvat tejash funksiyasi:\n\n• Tungi mavzuni yoqadi\n• Fondagi harakatlar, vizual effektlar va “Ok Google” kabi boshqa funksiyalarni faolsizlantiradi"</string> <string name="data_saver_description" msgid="4995164271550590517">"Trafik tejash rejimida ayrim ilovalar uchun orqa fonda internetdan foydalanish imkoniyati cheklanadi. Siz ishlatayotgan ilova zaruratga qarab internet-trafik sarflashi mumkin, biroq cheklangan miqdorda. Masalan, rasmlar ustiga bosmaguningizcha ular yuklanmaydi."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Trafik tejash yoqilsinmi?"</string> @@ -1894,7 +1894,7 @@ <string name="app_suspended_title" msgid="888873445010322650">"Ilova ishlamayapti"</string> <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ishlamayapti. Uning ishlashini <xliff:g id="APP_NAME_1">%2$s</xliff:g> cheklamoqda."</string> <string name="app_suspended_more_details" msgid="211260942831587014">"Batafsil"</string> - <string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Ilovani ishga tushirish"</string> + <string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Ilovani pauzadan chiqarish"</string> <string name="work_mode_off_title" msgid="5503291976647976560">"Ish profili yoqilsinmi?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Ishga oid ilovalar, bildirishnomalar, ma’lumotlar va boshqa ish profili imkoniyatlari yoqiladi"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Yoqish"</string> @@ -2009,7 +2009,7 @@ <string name="notification_feedback_indicator" msgid="663476517711323016">"Fikr-mulohaza yuborish"</string> <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Kun tartibi rejimi haqidagi bildirishnoma"</string> <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Batareya quvvati odatdagidan ertaroq tugashi mumkin"</string> - <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Batareya quvvati uzoqroq ishlashi uchun Tejamkor rejim yoqildi"</string> + <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Batareya quvvatini uzoqroq vaqtga yetkazish uchun quvvat tejash rejimi yoqildi"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Quvvat tejash"</string> <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Quvvat tejash rejimi faolsizlantirildi"</string> <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefon yetarli quvvatlandi. Funksiyalar endi cheklovlarsiz ishlaydi."</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Yangi: Ekran lupasi"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Ekranni toʻliq yoki qisman kattalashtirish mumkin"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Sozlamalar orqali yoqish"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Yopish"</string> </resources> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 296261f850e8..7533196bbff7 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Dịch vụ GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Dịch vụ Thông báo của cảm biến"</string> <string name="twilight_service" msgid="8964898045693187224">"Dịch vụ Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Trình phát hiện múi giờ (Không có kết nối)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Thiết bị của bạn sẽ bị xóa"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Không thể sử dụng ứng dụng quản trị. Thiết bị của bạn sẽ bị xóa ngay bây giờ.\n\nHãy liên hệ với quản trị viên của tổ chức nếu bạn có thắc mắc."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> đã tắt tính năng in."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Kết nối USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Ứng dụng đang chạy"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Các ứng dụng tiêu thụ pin"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Phóng to"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang sử dụng pin"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ứng dụng đang sử dụng pin"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Nhấn để biết chi tiết về mức sử dụng dữ liệu và pin"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Tính năng mới: Phóng to cửa sổ"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Giờ đây, bạn có thể phóng to một phần hoặc toàn màn hình"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Bật trong phần Cài đặt"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Đóng"</string> </resources> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index a27e7b1ba94c..811992ec941a 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS 服务"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"传感器通知服务"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight 服务"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"时区检测器(无网络连接)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"系统将清空您的设备"</string> <string name="factory_reset_message" msgid="2657049595153992213">"无法使用管理应用,系统现在将清空您的设备。\n\n如有疑问,请与您所在单位的管理员联系。"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"“<xliff:g id="OWNER_APP">%s</xliff:g>”已停用打印功能。"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB 连接"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"应用正在运行中"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"消耗电量的应用"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"放大功能"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>正在消耗电量"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 个应用正在消耗电量"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"点按即可详细了解电量和流量消耗情况"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"新功能:窗口放大镜"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"您现在可以放大屏幕上的部分或所有内容"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"在“设置”中开启"</string> + <string name="dismiss_action" msgid="1728820550388704784">"关闭"</string> </resources> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index 5099ebfd463f..25807ca2477d 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS 服務"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"感應器通知服務"</string> <string name="twilight_service" msgid="8964898045693187224">"暮光服務"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"時區偵測器 (沒有連線)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"您的裝置將被清除"</string> <string name="factory_reset_message" msgid="2657049595153992213">"無法使用管理員應用程式。系統會現在清除您的裝置。\n\n如有任何疑問,請聯絡您的機構管理員。"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"「<xliff:g id="OWNER_APP">%s</xliff:g>」暫停了列印。"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB 連線"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"應用程式正在執行"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"耗用電量的應用程式"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"放大"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在使用電量"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個應用程式正在使用電量"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"輕按即可查看電池和數據用量詳情"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"新功能:視窗放大鏡"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"您現在可以放大部分或整個畫面"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"在「設定」中開啟"</string> + <string name="dismiss_action" msgid="1728820550388704784">"關閉"</string> </resources> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 31bd99be57b1..238a89098289 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS 服務"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"感應器通知服務"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight 服務"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"時區偵測器 (不必連上網路)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"你的裝置資料將遭到清除"</string> <string name="factory_reset_message" msgid="2657049595153992213">"無法使用管理應用程式,系統現在將清除你裝置中的資料。\n\n如有任何問題,請與貴機構的管理員聯絡。"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"「<xliff:g id="OWNER_APP">%s</xliff:g>」已停用列印功能。"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB 連線"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"應用程式執行中"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"正在耗用電量的應用程式"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"放大"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在耗用電量"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個應用程式正在耗用電量"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"輕觸即可查看電池和數據用量詳情"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"新功能:視窗放大鏡"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"你可以放大局部或整個畫面"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"在「設定」中開啟"</string> + <string name="dismiss_action" msgid="1728820550388704784">"關閉"</string> </resources> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index 28eed9b98efd..6a23502c87ee 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Isevisi ye-GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Isevisi Yesaziso Senzwa"</string> <string name="twilight_service" msgid="8964898045693187224">"Isevisi Yangovivi"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Isitholi Sezoni Yesikhathi (Akukho ukuxhumana)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Idivayisi yakho izosulwa"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Uhlelo lokusebenza lomlawuli alikwazi ukusetshenziswa. Idivayisi yakho manje izosuswa.\n\nUma unemibuzo, xhumana nomlawuli wezinhlangano zakho."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Ukuphrinta kukhutshazwe nge-<xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Ukuxhumeka kwe-USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Uhlelo loksuebenza olusebenzayo"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Izinhlelo zokusebenza ezidla ibhethri"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ukukhuliswa"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> isebenzisa ibhethri"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> izinhlelo zokusebenza zisebenzisa ibhethri"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Thepha ngemininingwane ekusetshenzisweni kwebhethri nedatha"</string> @@ -817,7 +817,7 @@ <string name="relationTypeReferredBy" msgid="5285082289602849400">"Kusikiselwe ngu-"</string> <string name="relationTypeRelative" msgid="3396498519818009134">"Isihlobo"</string> <string name="relationTypeSister" msgid="3721676005094140671">"Usisi"</string> - <string name="relationTypeSpouse" msgid="6916682664436031703">"Umlingane"</string> + <string name="relationTypeSpouse" msgid="6916682664436031703">"Umlingani"</string> <string name="sipAddressTypeCustom" msgid="6283889809842649336">"Ngokwezifiso"</string> <string name="sipAddressTypeHome" msgid="5918441930656878367">"Ekhaya"</string> <string name="sipAddressTypeWork" msgid="7873967986701216770">"Umsebenzi"</string> @@ -2190,12 +2190,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Okusha: Isikhulisi sewindi"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Manje usungakwazi ukukhulisa esinye noma sonke isikrini sakho"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Vula Kumasethingi"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Cashisa"</string> </resources> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 03e64a4038ad..f4c30634ae04 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -3334,11 +3334,11 @@ <!-- Sets whether this ViewGroup should split MotionEvents to separate child views during touch event dispatch. - If false (default), touch events will be dispatched to + If false (default prior to HONEYCOMB), touch events will be dispatched to the child view where the first pointer went down until the last pointer goes up. - If true, touch events may be dispatched to multiple children. - MotionEvents for each pointer will be dispatched to the child + If true (default for HONEYCOMB and later), touch events may be dispatched to + multiple children. MotionEvents for each pointer will be dispatched to the child view where the initial ACTION_DOWN event happened. See {@link android.view.ViewGroup#setMotionEventSplittingEnabled(boolean)} for more information. --> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 85b19e7de04b..060c8b1144e5 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -226,6 +226,9 @@ to share specific features explicitly because they are being built together. --> <flag name="signatureOrSystem" value="3" /> + <!-- <strong>Base permission type</strong>: a permission that is managed internally by the + system and only granted according to the protection flags. --> + <flag name="internal" value="4" /> <!-- Additional flag from base permission type: this permission can also be granted to any applications installed as privileged apps on the system image. Please avoid using this option, as the @@ -306,6 +309,8 @@ <!-- Additional flag from base permission type: this permission will be granted to the recents app. --> <flag name="recents" value="0x2000000" /> + <!-- Additional flag from base permission type: this permission is managed by role. --> + <flag name="role" value="0x4000000" /> </attr> <!-- Flags indicating more context for a permission group. --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 40e11cb92d3e..03ba83c6bd2e 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -3303,6 +3303,10 @@ is non-interactive. --> <bool name="config_cameraDoubleTapPowerGestureEnabled">true</bool> + <!-- Allow the gesture to quick tap the power button multiple times to start the emergency sos + experience while the device is non-interactive. --> + <bool name="config_emergencyGestureEnabled">true</bool> + <!-- Allow the gesture power + volume up to change the ringer mode while the device is interactive. --> <bool name="config_volumeHushGestureEnabled">true</bool> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index e50eee6afa91..aff0695bb14e 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2823,6 +2823,7 @@ <java-symbol type="bool" name="config_cameraDoubleTapPowerGestureEnabled" /> <java-symbol type="integer" name="config_cameraLiftTriggerSensorType" /> <java-symbol type="string" name="config_cameraLiftTriggerSensorStringType" /> + <java-symbol type="bool" name="config_emergencyGestureEnabled" /> <java-symbol type="bool" name="config_volumeHushGestureEnabled" /> <java-symbol type="drawable" name="platlogo_m" /> diff --git a/core/tests/ConnectivityManagerTest/OWNERS b/core/tests/ConnectivityManagerTest/OWNERS new file mode 100644 index 000000000000..aa87958f1d53 --- /dev/null +++ b/core/tests/ConnectivityManagerTest/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/net/OWNERS diff --git a/core/tests/PackageInstallerSessions/OWNERS b/core/tests/PackageInstallerSessions/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/core/tests/PackageInstallerSessions/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/core/tests/benchmarks/src/android/net/OWNERS b/core/tests/benchmarks/src/android/net/OWNERS new file mode 100644 index 000000000000..aa87958f1d53 --- /dev/null +++ b/core/tests/benchmarks/src/android/net/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/net/OWNERS diff --git a/core/tests/bluetoothtests/OWNERS b/core/tests/bluetoothtests/OWNERS new file mode 100644 index 000000000000..98bb87716207 --- /dev/null +++ b/core/tests/bluetoothtests/OWNERS @@ -0,0 +1 @@ +include /core/java/android/bluetooth/OWNERS diff --git a/core/tests/coretests/apks/OWNERS b/core/tests/coretests/apks/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/core/tests/coretests/apks/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/core/tests/coretests/src/android/accessibilityservice/OWNERS b/core/tests/coretests/src/android/accessibilityservice/OWNERS new file mode 100644 index 000000000000..b74281edbf52 --- /dev/null +++ b/core/tests/coretests/src/android/accessibilityservice/OWNERS @@ -0,0 +1 @@ +include /core/java/android/view/accessibility/OWNERS diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java index 4654f63a2a91..b2b34d64b12c 100644 --- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java @@ -26,6 +26,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; +import android.app.servertransaction.TestUtils.LaunchActivityItemBuilder; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; @@ -43,6 +44,8 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.function.Supplier; + /** * Tests for {@link ObjectPool}. * @@ -144,24 +147,22 @@ public class ObjectPoolTests { persistableBundle.putInt("k", 4); IBinder assistToken = new Binder(); - LaunchActivityItem emptyItem = LaunchActivityItem.obtain(null, 0, null, null, null, null, - null, null, 0, null, null, null, null, false, null, null, null); - LaunchActivityItem item = LaunchActivityItem.obtain(intent, ident, activityInfo, - config(), overrideConfig, compat, referrer, null /* voiceInteractor */, - procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(), - true /* isForward */, null /* profilerInfo */, assistToken, - null /* fixedRotationAdjustments */); + Supplier<LaunchActivityItem> itemSupplier = () -> new LaunchActivityItemBuilder() + .setIntent(intent).setIdent(ident).setInfo(activityInfo).setCurConfig(config()) + .setOverrideConfig(overrideConfig).setCompatInfo(compat).setReferrer(referrer) + .setProcState(procState).setState(bundle).setPersistentState(persistableBundle) + .setPendingResults(resultInfoList()).setPendingNewIntents(referrerIntentList()) + .setIsForward(true).setAssistToken(assistToken).build(); + + LaunchActivityItem emptyItem = new LaunchActivityItemBuilder().build(); + LaunchActivityItem item = itemSupplier.get(); assertNotSame(item, emptyItem); assertFalse(item.equals(emptyItem)); item.recycle(); assertEquals(item, emptyItem); - LaunchActivityItem item2 = LaunchActivityItem.obtain(intent, ident, activityInfo, - config(), overrideConfig, compat, referrer, null /* voiceInteractor */, - procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(), - true /* isForward */, null /* profilerInfo */, assistToken, - null /* fixedRotationAdjustments */); + LaunchActivityItem item2 = itemSupplier.get(); assertSame(item, item2); assertFalse(item2.equals(emptyItem)); } diff --git a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java index d125fe790eba..7e9933c8d9df 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java +++ b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java @@ -18,11 +18,19 @@ package android.app.servertransaction; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; +import android.app.ProfilerInfo; import android.app.ResultInfo; import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.res.CompatibilityInfo; import android.content.res.Configuration; +import android.os.Bundle; +import android.os.IBinder; +import android.os.PersistableBundle; import android.util.MergedConfiguration; +import android.view.DisplayAdjustments.FixedRotationAdjustments; +import com.android.internal.app.IVoiceInteractor; import com.android.internal.content.ReferrerIntent; import java.util.ArrayList; @@ -81,4 +89,117 @@ class TestUtils { return referrerIntents; } + + static class LaunchActivityItemBuilder { + private Intent mIntent; + private int mIdent; + private ActivityInfo mInfo; + private Configuration mCurConfig; + private Configuration mOverrideConfig; + private CompatibilityInfo mCompatInfo; + private String mReferrer; + private IVoiceInteractor mVoiceInteractor; + private int mProcState; + private Bundle mState; + private PersistableBundle mPersistentState; + private List<ResultInfo> mPendingResults; + private List<ReferrerIntent> mPendingNewIntents; + private boolean mIsForward; + private ProfilerInfo mProfilerInfo; + private IBinder mAssistToken; + private FixedRotationAdjustments mFixedRotationAdjustments; + + LaunchActivityItemBuilder setIntent(Intent intent) { + mIntent = intent; + return this; + } + + LaunchActivityItemBuilder setIdent(int ident) { + mIdent = ident; + return this; + } + + LaunchActivityItemBuilder setInfo(ActivityInfo info) { + mInfo = info; + return this; + } + + LaunchActivityItemBuilder setCurConfig(Configuration curConfig) { + mCurConfig = curConfig; + return this; + } + + LaunchActivityItemBuilder setOverrideConfig(Configuration overrideConfig) { + mOverrideConfig = overrideConfig; + return this; + } + + LaunchActivityItemBuilder setCompatInfo(CompatibilityInfo compatInfo) { + mCompatInfo = compatInfo; + return this; + } + + LaunchActivityItemBuilder setReferrer(String referrer) { + mReferrer = referrer; + return this; + } + + LaunchActivityItemBuilder setVoiceInteractor(IVoiceInteractor voiceInteractor) { + mVoiceInteractor = voiceInteractor; + return this; + } + + LaunchActivityItemBuilder setProcState(int procState) { + mProcState = procState; + return this; + } + + LaunchActivityItemBuilder setState(Bundle state) { + mState = state; + return this; + } + + LaunchActivityItemBuilder setPersistentState(PersistableBundle persistentState) { + mPersistentState = persistentState; + return this; + } + + LaunchActivityItemBuilder setPendingResults(List<ResultInfo> pendingResults) { + mPendingResults = pendingResults; + return this; + } + + LaunchActivityItemBuilder setPendingNewIntents(List<ReferrerIntent> pendingNewIntents) { + mPendingNewIntents = pendingNewIntents; + return this; + } + + LaunchActivityItemBuilder setIsForward(boolean isForward) { + mIsForward = isForward; + return this; + } + + LaunchActivityItemBuilder setProfilerInfo(ProfilerInfo profilerInfo) { + mProfilerInfo = profilerInfo; + return this; + } + + LaunchActivityItemBuilder setAssistToken(IBinder assistToken) { + mAssistToken = assistToken; + return this; + } + + LaunchActivityItemBuilder setFixedRotationAdjustments(FixedRotationAdjustments fra) { + mFixedRotationAdjustments = fra; + return this; + } + + LaunchActivityItem build() { + return LaunchActivityItem.obtain(mIntent, mIdent, mInfo, + mCurConfig, mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, + mProcState, mState, mPersistentState, mPendingResults, mPendingNewIntents, + mIsForward, mProfilerInfo, mAssistToken, null /* activityClientController */, + mFixedRotationAdjustments); + } + } } diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java index 0ae789af477c..32f892924ac5 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java @@ -41,6 +41,7 @@ import android.app.Activity; import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.app.servertransaction.ActivityLifecycleItem.LifecycleState; +import android.app.servertransaction.TestUtils.LaunchActivityItemBuilder; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; @@ -263,13 +264,7 @@ public class TransactionExecutorTests { // A previous queued launch transaction runs on main thread (execute). final ClientTransaction launchTransaction = ClientTransaction.obtain(null /* client */, token /* activityToken */); - final LaunchActivityItem launchItem = spy(LaunchActivityItem.obtain( - null /* intent */, 0 /* ident */, null /* info */, null /* curConfig */, - null, /* overrideConfig */ null /* compatInfo */, null /* referrer */ , - null /* voiceInteractor */, 0 /* procState */, null /* state */, - null /* persistentState */, null /* pendingResults */, - null /* pendingNewIntents */, false /* isForward */, null /* profilerInfo */, - null /* assistToken */, null /* fixedRotationAdjustments */)); + final LaunchActivityItem launchItem = spy(new LaunchActivityItemBuilder().build()); launchTransaction.addCallback(launchItem); mExecutor.execute(launchTransaction); diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java index 7e992989426d..e1c7146908d6 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java @@ -29,6 +29,7 @@ import android.app.IApplicationThread; import android.app.IInstrumentationWatcher; import android.app.IUiAutomationConnection; import android.app.ProfilerInfo; +import android.app.servertransaction.TestUtils.LaunchActivityItemBuilder; import android.content.AutofillOptions; import android.content.ComponentName; import android.content.ContentCaptureOptions; @@ -195,11 +196,14 @@ public class TransactionParcelTests { FixedRotationAdjustments fixedRotationAdjustments = new FixedRotationAdjustments( Surface.ROTATION_90, 1920, 1080, DisplayCutout.NO_CUTOUT); - LaunchActivityItem item = LaunchActivityItem.obtain(intent, ident, activityInfo, - config(), overrideConfig, compat, referrer, null /* voiceInteractor */, - procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(), - true /* isForward */, null /* profilerInfo */, new Binder(), - fixedRotationAdjustments); + LaunchActivityItem item = new LaunchActivityItemBuilder() + .setIntent(intent).setIdent(ident).setInfo(activityInfo).setCurConfig(config()) + .setOverrideConfig(overrideConfig).setCompatInfo(compat).setReferrer(referrer) + .setProcState(procState).setState(bundle).setPersistentState(persistableBundle) + .setPendingResults(resultInfoList()).setPendingNewIntents(referrerIntentList()) + .setIsForward(true).setAssistToken(new Binder()) + .setFixedRotationAdjustments(fixedRotationAdjustments).build(); + writeAndPrepareForReading(item); // Read from parcel and assert diff --git a/core/tests/coretests/src/android/database/OWNERS b/core/tests/coretests/src/android/database/OWNERS new file mode 100644 index 000000000000..bb9a2ca27ba9 --- /dev/null +++ b/core/tests/coretests/src/android/database/OWNERS @@ -0,0 +1 @@ +include /core/java/android/database/OWNERS diff --git a/core/tests/coretests/src/android/net/OWNERS b/core/tests/coretests/src/android/net/OWNERS new file mode 100644 index 000000000000..aa87958f1d53 --- /dev/null +++ b/core/tests/coretests/src/android/net/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/net/OWNERS diff --git a/core/tests/coretests/src/android/os/VibratorInfoTest.java b/core/tests/coretests/src/android/os/VibratorInfoTest.java new file mode 100644 index 000000000000..89411902bb6b --- /dev/null +++ b/core/tests/coretests/src/android/os/VibratorInfoTest.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +import android.platform.test.annotations.Presubmit; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@Presubmit +@RunWith(JUnit4.class) +public class VibratorInfoTest { + + @Test + public void testHasAmplitudeControl() { + assertFalse(createInfo(/* capabilities= */ 0).hasAmplitudeControl()); + assertTrue(createInfo(VibratorInfo.CAPABILITY_COMPOSE_EFFECTS + | VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL).hasAmplitudeControl()); + } + + @Test + public void testHasCapabilities() { + assertTrue(createInfo(VibratorInfo.CAPABILITY_COMPOSE_EFFECTS) + .hasCapability(VibratorInfo.CAPABILITY_COMPOSE_EFFECTS)); + assertFalse(createInfo(VibratorInfo.CAPABILITY_COMPOSE_EFFECTS) + .hasCapability(VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL)); + } + + @Test + public void testIsEffectSupported() { + VibratorInfo info = new VibratorInfo(/* id= */ 0, /* capabilities= */0, + new int[]{VibrationEffect.EFFECT_CLICK}, null); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN, + createInfo(/* capabilities= */ 0).isEffectSupported(VibrationEffect.EFFECT_CLICK)); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_YES, + info.isEffectSupported(VibrationEffect.EFFECT_CLICK)); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_NO, + info.isEffectSupported(VibrationEffect.EFFECT_TICK)); + } + + @Test + public void testIsPrimitiveSupported() { + VibratorInfo info = new VibratorInfo(/* id= */ 0, VibratorInfo.CAPABILITY_COMPOSE_EFFECTS, + null, new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}); + assertTrue(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK)); + assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_TICK)); + + // Returns false when there is no compose capability. + info = new VibratorInfo(/* id= */ 0, /* capabilities= */ 0, + null, new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}); + assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK)); + } + + @Test + public void testEquals() { + VibratorInfo empty = new VibratorInfo(1, 0, null, null); + VibratorInfo complete = new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL, + new int[]{VibrationEffect.EFFECT_CLICK}, + new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}); + + assertEquals(complete, complete); + assertEquals(complete, new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL, + new int[]{VibrationEffect.EFFECT_CLICK}, + new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK})); + + assertFalse(empty.equals(new VibratorInfo(1, 0, new int[]{}, new int[]{}))); + assertFalse(complete.equals(new VibratorInfo(1, VibratorInfo.CAPABILITY_COMPOSE_EFFECTS, + new int[]{VibrationEffect.EFFECT_CLICK}, + new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}))); + assertFalse(complete.equals(new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL, + new int[]{}, new int[]{}))); + assertFalse(complete.equals(new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL, + null, new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}))); + assertFalse(complete.equals(new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL, + new int[]{VibrationEffect.EFFECT_CLICK}, null))); + } + + @Test + public void testSerialization() { + VibratorInfo original = new VibratorInfo(1, VibratorInfo.CAPABILITY_COMPOSE_EFFECTS, + new int[]{VibrationEffect.EFFECT_CLICK}, null); + + Parcel parcel = Parcel.obtain(); + original.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + VibratorInfo restored = VibratorInfo.CREATOR.createFromParcel(parcel); + assertEquals(original, restored); + } + + private static VibratorInfo createInfo(long capabilities) { + return new VibratorInfo(/* id= */ 0, capabilities, null, null); + } +} diff --git a/core/tests/coretests/src/android/os/VibratorTest.java b/core/tests/coretests/src/android/os/VibratorTest.java index c3d84ecc2abf..575a1be905f2 100644 --- a/core/tests/coretests/src/android/os/VibratorTest.java +++ b/core/tests/coretests/src/android/os/VibratorTest.java @@ -55,6 +55,26 @@ public class VibratorTest { } @Test + public void areEffectsSupported_returnsArrayOfSameSize() { + assertEquals(0, mVibratorSpy.areEffectsSupported(new int[0]).length); + assertEquals(1, + mVibratorSpy.areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK}).length); + assertEquals(2, + mVibratorSpy.areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK, + VibrationEffect.EFFECT_TICK}).length); + } + + @Test + public void arePrimitivesSupported_returnsArrayOfSameSize() { + assertEquals(0, mVibratorSpy.arePrimitivesSupported(new int[0]).length); + assertEquals(1, mVibratorSpy.arePrimitivesSupported( + new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}).length); + assertEquals(2, mVibratorSpy.arePrimitivesSupported( + new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK, + VibrationEffect.Composition.PRIMITIVE_QUICK_RISE}).length); + } + + @Test public void vibrate_withAudioAttributes_createsVibrationAttributesWithSameUsage() { VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK); AudioAttributes audioAttributes = new AudioAttributes.Builder().setUsage( diff --git a/core/tests/coretests/src/com/android/internal/accessibility/OWNERS b/core/tests/coretests/src/com/android/internal/accessibility/OWNERS new file mode 100644 index 000000000000..b74281edbf52 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/accessibility/OWNERS @@ -0,0 +1 @@ +include /core/java/android/view/accessibility/OWNERS diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/OWNERS b/core/tests/coretests/src/com/android/internal/inputmethod/OWNERS new file mode 100644 index 000000000000..5deb2ce8f24b --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/inputmethod/OWNERS @@ -0,0 +1 @@ +include /core/java/android/view/inputmethod/OWNERS diff --git a/core/tests/coretests/src/com/android/internal/jank/OWNERS b/core/tests/coretests/src/com/android/internal/jank/OWNERS new file mode 100644 index 000000000000..faece0818a09 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/jank/OWNERS @@ -0,0 +1 @@ +include /core/java/com/android/internal/jank/OWNERS
\ No newline at end of file diff --git a/core/tests/coretests/src/com/android/internal/os/KernelSingleProcessCpuThreadReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelSingleProcessCpuThreadReaderTest.java index b5720a262b3d..2de800bb6d00 100644 --- a/core/tests/coretests/src/com/android/internal/os/KernelSingleProcessCpuThreadReaderTest.java +++ b/core/tests/coretests/src/com/android/internal/os/KernelSingleProcessCpuThreadReaderTest.java @@ -19,122 +19,87 @@ package com.android.internal.os; import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertTrue; - -import android.content.Context; -import android.os.FileUtils; - -import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import org.junit.After; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import java.io.File; import java.io.IOException; -import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; @SmallTest @RunWith(AndroidJUnit4.class) public class KernelSingleProcessCpuThreadReaderTest { - private File mProcDirectory; - - @Before - public void setUp() { - Context context = InstrumentationRegistry.getContext(); - mProcDirectory = context.getDir("proc", Context.MODE_PRIVATE); - } - - @After - public void tearDown() throws Exception { - FileUtils.deleteContents(mProcDirectory); - } - @Test public void getProcessCpuUsage() throws IOException { - setupDirectory(42, - new int[] {42, 1, 2, 3}, - new int[] {1000, 2000}, - // Units are 10ms aka 10000Us - new int[][] {{100, 200}, {0, 200}, {100, 300}, {0, 600}}, - new int[] {4500, 500}); + // Units are nanoseconds + MockCpuTimeInStateReader mockReader = new MockCpuTimeInStateReader(4, new String[] { + "0:1000000000 2000000000 3000000000:4000000000", + "1:100000000 200000000 300000000:400000000", + }); KernelSingleProcessCpuThreadReader reader = new KernelSingleProcessCpuThreadReader(42, - mProcDirectory.toPath()); + mockReader); + reader.setSelectedThreadIds(new int[] {2, 3}); + reader.startTrackingThreadCpuTimes(); KernelSingleProcessCpuThreadReader.ProcessCpuUsage processCpuUsage = - reader.getProcessCpuUsage(new int[] {2, 3}); - assertThat(processCpuUsage.threadCpuTimesMillis).isEqualTo(new long[] {2000, 13000}); - assertThat(processCpuUsage.selectedThreadCpuTimesMillis).isEqualTo(new long[] {1000, 9000}); - assertThat(processCpuUsage.processCpuTimesMillis).isEqualTo(new long[] {6666, 43333}); + reader.getProcessCpuUsage(); + assertThat(mockReader.mTrackedTgid).isEqualTo(42); + // The strings are formatted as <TID TGID AGG_KEY>, where AGG_KEY is 1 for binder + // threads and 0 for all other threads. + assertThat(mockReader.mTrackedTasks).containsExactly( + "2 1", + "3 1"); + assertThat(processCpuUsage.threadCpuTimesMillis).isEqualTo( + new long[] {1100, 2200, 3300, 4400}); + assertThat(processCpuUsage.selectedThreadCpuTimesMillis).isEqualTo( + new long[] {100, 200, 300, 400}); } @Test public void getCpuFrequencyCount() throws IOException { - setupDirectory(13, - new int[] {13}, - new int[] {1000, 2000, 3000}, - new int[][] {{100, 200, 300}}, - new int[] {14, 15}); + MockCpuTimeInStateReader mockReader = new MockCpuTimeInStateReader(3, new String[0]); KernelSingleProcessCpuThreadReader reader = new KernelSingleProcessCpuThreadReader(13, - mProcDirectory.toPath()); + mockReader); int cpuFrequencyCount = reader.getCpuFrequencyCount(); assertThat(cpuFrequencyCount).isEqualTo(3); } - private void setupDirectory(int pid, int[] threadIds, int[] cpuFrequencies, - int[][] threadCpuTimes, int[] processCpuTimes) - throws IOException { - - assertTrue(mProcDirectory.toPath().resolve("self").toFile().mkdirs()); - - try (OutputStream timeInStateStream = - Files.newOutputStream( - mProcDirectory.toPath().resolve("self").resolve("time_in_state"))) { - for (int i = 0; i < cpuFrequencies.length; i++) { - final String line = cpuFrequencies[i] + " 0\n"; - timeInStateStream.write(line.getBytes()); - } + public static class MockCpuTimeInStateReader implements + KernelSingleProcessCpuThreadReader.CpuTimeInStateReader { + private final int mCpuFrequencyCount; + private final String[] mAggregatedTaskCpuFreqTimes; + public int mTrackedTgid; + public List<String> mTrackedTasks = new ArrayList<>(); + + public MockCpuTimeInStateReader(int cpuFrequencyCount, + String[] aggregatedTaskCpuFreqTimes) { + mCpuFrequencyCount = cpuFrequencyCount; + mAggregatedTaskCpuFreqTimes = aggregatedTaskCpuFreqTimes; } - Path processPath = mProcDirectory.toPath().resolve(String.valueOf(pid)); + @Override + public int getCpuFrequencyCount() { + return mCpuFrequencyCount; + } - // Make /proc/$PID - assertTrue(processPath.toFile().mkdirs()); + @Override + public boolean startTrackingProcessCpuTimes(int tgid) { + mTrackedTgid = tgid; + return true; + } - // Write /proc/$PID/stat. Only the fields 14-17 matter. - try (OutputStream timeInStateStream = Files.newOutputStream(processPath.resolve("stat"))) { - timeInStateStream.write( - (pid + " (test) S 4 5 6 7 8 9 10 11 12 13 " - + processCpuTimes[0] + " " - + processCpuTimes[1] + " " - + "16 17 18 19 20 ...").getBytes()); + public boolean startAggregatingTaskCpuTimes(int pid, int aggregationKey) { + mTrackedTasks.add(pid + " " + aggregationKey); + return true; } - // Make /proc/$PID/task - final Path selfThreadsPath = processPath.resolve("task"); - assertTrue(selfThreadsPath.toFile().mkdirs()); - - // Make thread directories - for (int i = 0; i < threadIds.length; i++) { - // Make /proc/$PID/task/$TID - final Path threadPath = selfThreadsPath.resolve(String.valueOf(threadIds[i])); - assertTrue(threadPath.toFile().mkdirs()); - - // Make /proc/$PID/task/$TID/time_in_state - try (OutputStream timeInStateStream = - Files.newOutputStream(threadPath.resolve("time_in_state"))) { - for (int j = 0; j < cpuFrequencies.length; j++) { - final String line = cpuFrequencies[j] + " " + threadCpuTimes[i][j] + "\n"; - timeInStateStream.write(line.getBytes()); - } - } + public String[] getAggregatedTaskCpuFreqTimes(int pid) { + return mAggregatedTaskCpuFreqTimes; } } } diff --git a/core/tests/coretests/src/com/android/internal/os/SystemServerCpuThreadReaderTest.java b/core/tests/coretests/src/com/android/internal/os/SystemServerCpuThreadReaderTest.java index 121c637310c6..d116d4dcbe92 100644 --- a/core/tests/coretests/src/com/android/internal/os/SystemServerCpuThreadReaderTest.java +++ b/core/tests/coretests/src/com/android/internal/os/SystemServerCpuThreadReaderTest.java @@ -16,146 +16,86 @@ package com.android.internal.os; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertTrue; +import static com.google.common.truth.Truth.assertThat; -import android.content.Context; -import android.os.FileUtils; - -import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import org.junit.After; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import java.io.File; import java.io.IOException; -import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.Path; @SmallTest @RunWith(AndroidJUnit4.class) public class SystemServerCpuThreadReaderTest { - private File mProcDirectory; - - @Before - public void setUp() { - Context context = InstrumentationRegistry.getContext(); - mProcDirectory = context.getDir("proc", Context.MODE_PRIVATE); - } - - @After - public void tearDown() throws Exception { - FileUtils.deleteContents(mProcDirectory); - } @Test - public void testReaderDelta_firstTime() throws IOException { + public void testReadDelta() throws IOException { int pid = 42; - setupDirectory( - pid, - new int[] {42, 1, 2, 3}, - new int[] {1000, 2000}, - // Units are 10ms aka 10000Us - new int[][] {{100, 200}, {0, 200}, {0, 300}, {0, 400}}, - new int[] {1400, 1500}); - - SystemServerCpuThreadReader reader = new SystemServerCpuThreadReader( - mProcDirectory.toPath(), pid); + + MockCpuTimeInStateReader mockReader = new MockCpuTimeInStateReader(4); + // Units are nanoseconds + mockReader.setAggregatedTaskCpuFreqTimes(new String[] { + "0:1000000000 2000000000 3000000000:4000000000", + "1:100000000 200000000 300000000:400000000", + }); + + SystemServerCpuThreadReader reader = new SystemServerCpuThreadReader(pid, mockReader); reader.setBinderThreadNativeTids(new int[] {1, 3}); + + // The first invocation of readDelta populates the "last" snapshot SystemServerCpuThreadReader.SystemServiceCpuThreadTimes systemServiceCpuThreadTimes = reader.readDelta(); - assertArrayEquals(new long[] {100 * 10000, 1100 * 10000}, - systemServiceCpuThreadTimes.threadCpuTimesUs); - assertArrayEquals(new long[] {0, 600 * 10000}, - systemServiceCpuThreadTimes.binderThreadCpuTimesUs); - } - - @Test - public void testReaderDelta_nextTime() throws IOException { - int pid = 42; - setupDirectory( - pid, - new int[] {42, 1, 2, 3}, - new int[] {1000, 2000}, - new int[][] {{100, 200}, {0, 200}, {0, 300}, {0, 400}}, - new int[] {1400, 1500}); - - SystemServerCpuThreadReader reader = new SystemServerCpuThreadReader( - mProcDirectory.toPath(), pid); - reader.setBinderThreadNativeTids(new int[] {1, 3}); - // First time, populate "last" snapshot - reader.readDelta(); + assertThat(systemServiceCpuThreadTimes.threadCpuTimesUs) + .isEqualTo(new long[] {1100000, 2200000, 3300000, 4400000}); + assertThat(systemServiceCpuThreadTimes.binderThreadCpuTimesUs) + .isEqualTo(new long[] {100000, 200000, 300000, 400000}); - FileUtils.deleteContents(mProcDirectory); - setupDirectory( - pid, - new int[] {42, 1, 2, 3}, - new int[] {1000, 2000}, - new int[][] {{500, 600}, {700, 800}, {900, 1000}, {1100, 1200}}, - new int[] {2400, 2500}); + mockReader.setAggregatedTaskCpuFreqTimes(new String[] { + "0:1010000000 2020000000 3030000000:4040000000", + "1:101000000 202000000 303000000:404000000", + }); - // Second time, get the actual delta - SystemServerCpuThreadReader.SystemServiceCpuThreadTimes systemServiceCpuThreadTimes = - reader.readDelta(); + // The second invocation gets the actual delta + systemServiceCpuThreadTimes = reader.readDelta(); - assertArrayEquals(new long[] {3100 * 10000, 2500 * 10000}, - systemServiceCpuThreadTimes.threadCpuTimesUs); - assertArrayEquals(new long[] {1800 * 10000, 1400 * 10000}, - systemServiceCpuThreadTimes.binderThreadCpuTimesUs); + assertThat(systemServiceCpuThreadTimes.threadCpuTimesUs) + .isEqualTo(new long[] {11000, 22000, 33000, 44000}); + assertThat(systemServiceCpuThreadTimes.binderThreadCpuTimesUs) + .isEqualTo(new long[] {1000, 2000, 3000, 4000}); } - private void setupDirectory(int pid, int[] threadIds, int[] cpuFrequencies, int[][] cpuTimes, - int[] processCpuTimes) - throws IOException { + public static class MockCpuTimeInStateReader implements + KernelSingleProcessCpuThreadReader.CpuTimeInStateReader { + private final int mCpuFrequencyCount; + private String[] mAggregatedTaskCpuFreqTimes; - assertTrue(mProcDirectory.toPath().resolve("self").toFile().mkdirs()); + MockCpuTimeInStateReader(int frequencyCount) { + mCpuFrequencyCount = frequencyCount; + } + + @Override + public int getCpuFrequencyCount() { + return mCpuFrequencyCount; + } + + @Override + public boolean startTrackingProcessCpuTimes(int tgid) { + return true; + } - try (OutputStream timeInStateStream = - Files.newOutputStream( - mProcDirectory.toPath().resolve("self").resolve("time_in_state"))) { - for (int i = 0; i < cpuFrequencies.length; i++) { - final String line = cpuFrequencies[i] + " 0\n"; - timeInStateStream.write(line.getBytes()); - } + public boolean startAggregatingTaskCpuTimes(int pid, int aggregationKey) { + return true; } - Path processPath = mProcDirectory.toPath().resolve(String.valueOf(pid)); - // Make /proc/$PID - assertTrue(processPath.toFile().mkdirs()); - - // Write /proc/$PID/stat. Only the fields 14-17 matter. - try (OutputStream timeInStateStream = Files.newOutputStream(processPath.resolve("stat"))) { - timeInStateStream.write( - (pid + " (test) S 4 5 6 7 8 9 10 11 12 13 " - + processCpuTimes[0] + " " - + processCpuTimes[1] + " " - + "16 17 18 19 20 ...").getBytes()); + public void setAggregatedTaskCpuFreqTimes(String[] mAggregatedTaskCpuFreqTimes) { + this.mAggregatedTaskCpuFreqTimes = mAggregatedTaskCpuFreqTimes; } - // Make /proc/$PID/task - final Path selfThreadsPath = processPath.resolve("task"); - assertTrue(selfThreadsPath.toFile().mkdirs()); - - // Make thread directories - for (int i = 0; i < threadIds.length; i++) { - // Make /proc/$PID/task/$TID - final Path threadPath = selfThreadsPath.resolve(String.valueOf(threadIds[i])); - assertTrue(threadPath.toFile().mkdirs()); - - // Make /proc/$PID/task/$TID/time_in_state - try (OutputStream timeInStateStream = - Files.newOutputStream(threadPath.resolve("time_in_state"))) { - for (int j = 0; j < cpuFrequencies.length; j++) { - final String line = cpuFrequencies[j] + " " + cpuTimes[i][j] + "\n"; - timeInStateStream.write(line.getBytes()); - } - } + public String[] getAggregatedTaskCpuFreqTimes(int pid) { + return mAggregatedTaskCpuFreqTimes; } } } diff --git a/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java index dbb36fbd1650..c8e858553e7d 100644 --- a/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java @@ -66,7 +66,6 @@ public class SystemServicePowerCalculatorTest { public void testCalculateApp() { // Test Power Profile has two CPU clusters with 3 and 4 speeds, thus 7 freq times total mMockSystemServerCpuThreadReader.setCpuTimes( - new long[] {10000, 15000, 20000, 25000, 30000, 35000, 40000}, new long[] {30000, 40000, 50000, 60000, 70000, 80000, 90000}, new long[] {20000, 30000, 40000, 50000, 60000, 70000, 80000}); @@ -146,9 +145,7 @@ public class SystemServicePowerCalculatorTest { super(null); } - public void setCpuTimes(long[] processCpuTimesUs, long[] threadCpuTimesUs, - long[] binderThreadCpuTimesUs) { - mThreadTimes.processCpuTimesUs = processCpuTimesUs; + public void setCpuTimes(long[] threadCpuTimesUs, long[] binderThreadCpuTimesUs) { mThreadTimes.threadCpuTimesUs = threadCpuTimesUs; mThreadTimes.binderThreadCpuTimesUs = binderThreadCpuTimesUs; } diff --git a/core/tests/coretests/src/com/android/internal/policy/OWNERS b/core/tests/coretests/src/com/android/internal/policy/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/policy/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/core/tests/coretests/src/com/android/internal/power/OWNERS b/core/tests/coretests/src/com/android/internal/power/OWNERS new file mode 100644 index 000000000000..d68066bb8c40 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/power/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/power/OWNERS diff --git a/core/tests/coretests/src/com/android/internal/statusbar/OWNERS b/core/tests/coretests/src/com/android/internal/statusbar/OWNERS new file mode 100644 index 000000000000..2e96c97c8bb3 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/statusbar/OWNERS @@ -0,0 +1 @@ +include /packages/SystemUI/OWNERS diff --git a/core/tests/devicestatetests/src/android/hardware/devicestate/OWNERS b/core/tests/devicestatetests/src/android/hardware/devicestate/OWNERS new file mode 100644 index 000000000000..d9b0e2e5ffa5 --- /dev/null +++ b/core/tests/devicestatetests/src/android/hardware/devicestate/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/devicestate/OWNERS diff --git a/core/tests/hdmitests/OWNERS b/core/tests/hdmitests/OWNERS new file mode 100644 index 000000000000..c3c47eda59d7 --- /dev/null +++ b/core/tests/hdmitests/OWNERS @@ -0,0 +1 @@ +include /core/java/android/hardware/hdmi/OWNERS diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java index 4c0de629c464..4ce072ccc894 100755 --- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java +++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java @@ -37,6 +37,7 @@ public class HdmiDeviceInfoTest { int deviceType = 0; int vendorId = 0x123456; String displayName = "test device"; + int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0; int powerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY; int deviceId = 3; int adopterId = 2; @@ -70,6 +71,16 @@ public class HdmiDeviceInfoTest { vendorId, displayName, powerStatus)) + .addEqualityGroup( + new HdmiDeviceInfo( + logicalAddr, + phyAddr, + portId, + deviceType, + vendorId, + displayName, + powerStatus, + cecVersion)) .testEquals(); } } diff --git a/core/tests/hosttests/test-apps/OWNERS b/core/tests/hosttests/test-apps/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/core/tests/hosttests/test-apps/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/core/tests/notificationtests/OWNERS b/core/tests/notificationtests/OWNERS new file mode 100644 index 000000000000..396fd1213aca --- /dev/null +++ b/core/tests/notificationtests/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/notification/OWNERS diff --git a/core/tests/overlaytests/OWNERS b/core/tests/overlaytests/OWNERS new file mode 100644 index 000000000000..afb98d416762 --- /dev/null +++ b/core/tests/overlaytests/OWNERS @@ -0,0 +1 @@ +include /core/java/android/content/om/OWNERS diff --git a/core/tests/packagemanagertests/OWNERS b/core/tests/packagemanagertests/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/core/tests/packagemanagertests/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/core/tests/powertests/OWNERS b/core/tests/powertests/OWNERS new file mode 100644 index 000000000000..d68066bb8c40 --- /dev/null +++ b/core/tests/powertests/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/power/OWNERS diff --git a/data/etc/OWNERS b/data/etc/OWNERS index 70d467829269..5efd0bd06b74 100644 --- a/data/etc/OWNERS +++ b/data/etc/OWNERS @@ -1 +1,13 @@ -per-file privapp-permissions-platform.xml = hackbod@android.com, jsharkey@android.com, svetoslavganov@google.com, toddke@google.com, yamasani@google.com, cbrubaker@google.com, jeffv@google.com, moltmann@google.com, lorenzo@google.com +cbrubaker@google.com +hackbod@android.com +hackbod@google.com +jeffv@google.com +jsharkey@android.com +jsharkey@google.com +lorenzo@google.com +moltmann@google.com +svetoslavganov@android.com +svetoslavganov@google.com +toddke@android.com +toddke@google.com +yamasani@google.com diff --git a/data/etc/car/OWNERS b/data/etc/car/OWNERS new file mode 100644 index 000000000000..09e257ce32ad --- /dev/null +++ b/data/etc/car/OWNERS @@ -0,0 +1 @@ +include platform/packages/services/Car:/OWNERS diff --git a/data/fonts/OWNERS b/data/fonts/OWNERS new file mode 100644 index 000000000000..a538331dd3f4 --- /dev/null +++ b/data/fonts/OWNERS @@ -0,0 +1 @@ +include /core/java/android/graphics/fonts/OWNERS diff --git a/drm/java/android/drm/OWNERS b/drm/java/android/drm/OWNERS new file mode 100644 index 000000000000..43871001c9ad --- /dev/null +++ b/drm/java/android/drm/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 49079 + +jtinker@google.com +robertshih@google.com diff --git a/errorprone/OWNERS b/errorprone/OWNERS new file mode 100644 index 000000000000..bddbdb364683 --- /dev/null +++ b/errorprone/OWNERS @@ -0,0 +1,2 @@ +jsharkey@android.com +jsharkey@google.com diff --git a/graphics/OWNERS b/graphics/OWNERS new file mode 100644 index 000000000000..a6d1bc37d27d --- /dev/null +++ b/graphics/OWNERS @@ -0,0 +1 @@ +include /core/java/android/graphics/OWNERS diff --git a/graphics/java/android/graphics/OWNERS b/graphics/java/android/graphics/OWNERS new file mode 100644 index 000000000000..61968890b837 --- /dev/null +++ b/graphics/java/android/graphics/OWNERS @@ -0,0 +1,6 @@ +# Bug component: 24939 + +romainguy@google.com +jreck@google.com +njawad@google.com +sumir@google.com diff --git a/graphics/java/android/graphics/ParcelableColorSpace.java b/graphics/java/android/graphics/ParcelableColorSpace.java index 326084924450..748d66cb5f6c 100644 --- a/graphics/java/android/graphics/ParcelableColorSpace.java +++ b/graphics/java/android/graphics/ParcelableColorSpace.java @@ -22,18 +22,19 @@ import android.os.Parcel; import android.os.Parcelable; /** - * A {@link Parcelable} {@link ColorSpace}. In order to enable parceling, the ColorSpace - * must be either a {@link ColorSpace.Named Named} ColorSpace or a {@link ColorSpace.Rgb} instance - * that has an ICC parametric transfer function as returned by {@link Rgb#getTransferParameters()}. + * A {@link Parcelable} wrapper for a {@link ColorSpace}. In order to enable parceling, the + * ColorSpace must be either a {@link ColorSpace.Named Named} ColorSpace or a + * {@link ColorSpace.Rgb} instance that has an ICC parametric transfer function as returned by + * {@link ColorSpace.Rgb#getTransferParameters()}. */ -public final class ParcelableColorSpace extends ColorSpace implements Parcelable { +public final class ParcelableColorSpace implements Parcelable { private final ColorSpace mColorSpace; /** * Checks if the given ColorSpace is able to be parceled. A ColorSpace can only be * parceled if it is a {@link ColorSpace.Named Named} ColorSpace or a {@link ColorSpace.Rgb} * instance that has an ICC parametric transfer function as returned by - * {@link Rgb#getTransferParameters()} + * {@link ColorSpace.Rgb#getTransferParameters()} */ public static boolean isParcelable(@NonNull ColorSpace colorSpace) { if (colorSpace.getId() == ColorSpace.MIN_ID) { @@ -57,7 +58,6 @@ public final class ParcelableColorSpace extends ColorSpace implements Parcelable * to be parceled. See {@link #isParcelable(ColorSpace)}. */ public ParcelableColorSpace(@NonNull ColorSpace colorSpace) { - super(colorSpace.getName(), colorSpace.getModel(), colorSpace.getId()); mColorSpace = colorSpace; if (mColorSpace.getId() == ColorSpace.MIN_ID) { @@ -139,31 +139,6 @@ public final class ParcelableColorSpace extends ColorSpace implements Parcelable }; @Override - public boolean isWideGamut() { - return mColorSpace.isWideGamut(); - } - - @Override - public float getMinValue(int component) { - return mColorSpace.getMinValue(component); - } - - @Override - public float getMaxValue(int component) { - return mColorSpace.getMaxValue(component); - } - - @Override - public @NonNull float[] toXyz(@NonNull float[] v) { - return mColorSpace.toXyz(v); - } - - @Override - public @NonNull float[] fromXyz(@NonNull float[] v) { - return mColorSpace.fromXyz(v); - } - - @Override public boolean equals(@Nullable Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -175,10 +150,4 @@ public final class ParcelableColorSpace extends ColorSpace implements Parcelable public int hashCode() { return mColorSpace.hashCode(); } - - /** @hide */ - @Override - long getNativeInstance() { - return mColorSpace.getNativeInstance(); - } } diff --git a/graphics/java/android/graphics/drawable/OWNERS b/graphics/java/android/graphics/drawable/OWNERS new file mode 100644 index 000000000000..61968890b837 --- /dev/null +++ b/graphics/java/android/graphics/drawable/OWNERS @@ -0,0 +1,6 @@ +# Bug component: 24939 + +romainguy@google.com +jreck@google.com +njawad@google.com +sumir@google.com diff --git a/graphics/java/android/graphics/drawable/shapes/OWNERS b/graphics/java/android/graphics/drawable/shapes/OWNERS new file mode 100644 index 000000000000..61968890b837 --- /dev/null +++ b/graphics/java/android/graphics/drawable/shapes/OWNERS @@ -0,0 +1,6 @@ +# Bug component: 24939 + +romainguy@google.com +jreck@google.com +njawad@google.com +sumir@google.com diff --git a/graphics/java/android/graphics/fonts/OWNERS b/graphics/java/android/graphics/fonts/OWNERS new file mode 100644 index 000000000000..e0a354e0983a --- /dev/null +++ b/graphics/java/android/graphics/fonts/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 24939 + +romainguy@google.com +nona@google.com +siyamed@google.com diff --git a/graphics/java/android/graphics/pdf/OWNERS b/graphics/java/android/graphics/pdf/OWNERS new file mode 100644 index 000000000000..f04e2008a437 --- /dev/null +++ b/graphics/java/android/graphics/pdf/OWNERS @@ -0,0 +1,8 @@ +# Bug component: 24939 + +romainguy@google.com +djsollen@google.com +sumir@google.com +svetoslavganov@android.com +svetoslavganov@google.com +moltmann@google.com diff --git a/graphics/java/android/graphics/text/OWNERS b/graphics/java/android/graphics/text/OWNERS new file mode 100644 index 000000000000..e0a354e0983a --- /dev/null +++ b/graphics/java/android/graphics/text/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 24939 + +romainguy@google.com +nona@google.com +siyamed@google.com diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl index add52fa5b436..a9d4094d5245 100644 --- a/keystore/java/android/security/IKeyChainService.aidl +++ b/keystore/java/android/security/IKeyChainService.aidl @@ -49,6 +49,7 @@ interface IKeyChainService { in byte[] privateKey, in byte[] userCert, in byte[] certChain, String alias, int uid); boolean removeKeyPair(String alias); boolean containsKeyPair(String alias); + int[] getGrants(String alias); // APIs used by Settings boolean deleteCaCertificate(String alias); diff --git a/libs/WindowManager/OWNERS b/libs/WindowManager/OWNERS index 063d4594f2fa..2c61df96eb03 100644 --- a/libs/WindowManager/OWNERS +++ b/libs/WindowManager/OWNERS @@ -1,3 +1,3 @@ set noparent -include ../../services/core/java/com/android/server/wm/OWNERS
\ No newline at end of file +include /services/core/java/com/android/server/wm/OWNERS diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java index 174c16afc75f..e68a7471fdaf 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -31,14 +31,12 @@ import android.os.Binder; import android.os.IBinder; import android.util.ArrayMap; import android.util.Log; -import android.util.Slog; import android.util.SparseArray; import android.view.SurfaceControl; import android.window.ITaskOrganizerController; import android.window.TaskAppearedInfo; import android.window.TaskOrganizer; -import androidx.annotation.BinderThread; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -47,7 +45,6 @@ import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.TransactionPool; -import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.startingsurface.StartingSurfaceDrawer; import java.io.PrintWriter; @@ -275,6 +272,12 @@ public class ShellTaskOrganizer extends TaskOrganizer { synchronized (mLock) { ProtoLog.v(WM_SHELL_TASK_ORG, "Task info changed taskId=%d", taskInfo.taskId); final TaskAppearedInfo data = mTasks.get(taskInfo.taskId); + if (data == null) { + // TODO(b/171749427): It means onTaskInfoChanged send before onTaskAppeared or + // after onTaskVanished, it should be fixed in controller side. + return; + } + final TaskListener oldListener = getTaskListener(data.getTaskInfo()); final TaskListener newListener = getTaskListener(taskInfo); mTasks.put(taskInfo.taskId, new TaskAppearedInfo(taskInfo, data.getLeash())); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java index 542867d83e29..e4121986bcb7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java @@ -22,6 +22,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY; import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import android.content.Context; @@ -89,7 +90,7 @@ public final class SplitWindowManager extends WindowlessWindowManager { PixelFormat.TRANSLUCENT); lp.token = new Binder(); lp.setTitle(DIVIDER_WINDOW_TITLE); - lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION; + lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY; mViewHost.setView(dividerView, lp); dividerView.setup(splitLayout, mViewHost, null /* dragListener */); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java index 625c0a7b5d19..a89c8bb29c1b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java @@ -54,7 +54,6 @@ import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.splitscreen.SplitScreen; -import java.util.Objects; import java.util.Optional; /** @@ -108,16 +107,22 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange DragLayout dragLayout = new DragLayout(context, mSplitScreen); rootView.addView(dragLayout, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)); - wm.addView(rootView, layoutParams); - - mDisplayDropTargets.put(displayId, - new PerDisplay(displayId, context, wm, rootView, dragLayout)); + try { + wm.addView(rootView, layoutParams); + mDisplayDropTargets.put(displayId, + new PerDisplay(displayId, context, wm, rootView, dragLayout)); + } catch (WindowManager.InvalidDisplayException e) { + Slog.w(TAG, "Unable to add view for display id: " + displayId); + } } @Override public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Display changed: %d", displayId); final PerDisplay pd = mDisplayDropTargets.get(displayId); + if (pd == null) { + return; + } pd.rootView.requestApplyInsets(); } @@ -125,6 +130,9 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange public void onDisplayRemoved(int displayId) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Display removed: %d", displayId); final PerDisplay pd = mDisplayDropTargets.get(displayId); + if (pd == null) { + return; + } pd.wm.removeViewImmediate(pd.rootView); mDisplayDropTargets.remove(displayId); } @@ -139,6 +147,10 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange final PerDisplay pd = mDisplayDropTargets.get(displayId); final ClipDescription description = event.getClipDescription(); + if (pd == null) { + return false; + } + if (event.getAction() == ACTION_DRAG_STARTED) { final boolean hasValidClipData = event.getClipData().getItemCount() > 0 && (description.hasMimeType(MIMETYPE_APPLICATION_ACTIVITY) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxTaskListener.java index 6e87f131ed95..490ef3296be6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxTaskListener.java @@ -164,8 +164,6 @@ public class LetterboxTaskListener implements ShellTaskOrganizer.TaskListener { switch (gravity) { case Gravity.TOP: positionInParent.y += taskBoundsWithInsets.top - activityBoundsWithInsets.top; - // Showing status bar decor view. - crop.top -= activityBoundsWithInsets.top - activityBounds.top; break; case Gravity.CENTER: positionInParent.y += @@ -187,8 +185,6 @@ public class LetterboxTaskListener implements ShellTaskOrganizer.TaskListener { final int gravity = mLetterboxConfigController.getLandscapeGravity(); // Align activity to the top. positionInParent.y += taskBoundsWithInsets.top - activityBoundsWithInsets.top; - // Showing status bar decor view. - crop.top -= activityBoundsWithInsets.top - activityBounds.top; switch (gravity) { case Gravity.LEFT: positionInParent.x += taskBoundsWithInsets.left - activityBoundsWithInsets.left; @@ -209,6 +205,53 @@ public class LetterboxTaskListener implements ShellTaskOrganizer.TaskListener { + " for task: #" + taskInfo.taskId); } } + + // New bounds of the activity after it's repositioned with required gravity. + Rect newActivityBounds = new Rect(activityBounds); + // Task's surfce will be repositioned to positionInParent together with the activity + // inside it so the new activity bounds are the original activity bounds offset by + // the task's offset. + newActivityBounds.offset( + positionInParent.x - taskBounds.left, positionInParent.y - taskBounds.top); + Rect newActivityBoundsWithInsets = new Rect(newActivityBounds); + newActivityBoundsWithInsets.intersect(displayBoundsWithInsets); + // Activity handles insets on its own (e.g. under status bar or navigation bar). + // crop that is calculated above crops all insets from an activity and below insets that + // can be shown are added back to the crop bounds (e.g. if activity is still shown at the + // top of the display then the top inset won't be cropped). + // After task's surface is repositioned, intersection between an activity and insets can + // change but if it doesn't, the activity should be shown under insets to maximize visible + // area. + // Also, an activity can use area under insets and insets shouldn't be cropped in this case + // regardless of a position on the screen. + final Rect activityInsetsFromCore = taskInfo.letterboxActivityInsets; + if (newActivityBounds.top - newActivityBoundsWithInsets.top + == activityBounds.top - activityBoundsWithInsets.top + // Check whether an activity is shown under inset. If it is, then the inset from + // WM Core and the inset computed here will be different because local insets + // doesn't take into account visibility of insets requested by the activity. + || activityBoundsWithInsets.top - activityBounds.top + != activityInsetsFromCore.top) { + crop.top -= activityBoundsWithInsets.top - activityBounds.top; + } + if (newActivityBounds.bottom - newActivityBoundsWithInsets.bottom + == activityBounds.bottom - activityBoundsWithInsets.bottom + || activityBounds.bottom - activityBoundsWithInsets.bottom + != activityInsetsFromCore.bottom) { + crop.bottom += activityBounds.bottom - activityBoundsWithInsets.bottom; + } + if (newActivityBounds.left - newActivityBoundsWithInsets.left + == activityBounds.left - activityBoundsWithInsets.left + || activityBoundsWithInsets.left - activityBounds.left + != activityInsetsFromCore.left) { + crop.left -= activityBoundsWithInsets.left - activityBounds.left; + } + if (newActivityBounds.right - newActivityBoundsWithInsets.right + == activityBounds.right - activityBoundsWithInsets.right + || activityBounds.right - activityBoundsWithInsets.right + != activityInsetsFromCore.right) { + crop.right += activityBounds.right - activityBoundsWithInsets.right; + } } private Insets getInsets() { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java index 5593268588fd..d59aec2cc446 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java @@ -20,7 +20,6 @@ import android.app.RemoteAction; import android.content.ComponentName; import android.content.pm.ParceledListSlice; import android.os.RemoteException; -import android.view.DisplayInfo; import android.view.IPinnedStackListener; import android.view.WindowManagerGlobal; @@ -85,18 +84,6 @@ public class PinnedStackListenerForwarder { } } - private void onDisplayInfoChanged(DisplayInfo displayInfo) { - for (PinnedStackListener listener : mListeners) { - listener.onDisplayInfoChanged(displayInfo); - } - } - - private void onConfigurationChanged() { - for (PinnedStackListener listener : mListeners) { - listener.onConfigurationChanged(); - } - } - private void onAspectRatioChanged(float aspectRatio) { for (PinnedStackListener listener : mListeners) { listener.onAspectRatioChanged(aspectRatio); @@ -134,20 +121,6 @@ public class PinnedStackListenerForwarder { } @Override - public void onDisplayInfoChanged(DisplayInfo displayInfo) { - mShellMainExecutor.execute(() -> { - PinnedStackListenerForwarder.this.onDisplayInfoChanged(displayInfo); - }); - } - - @Override - public void onConfigurationChanged() { - mShellMainExecutor.execute(() -> { - PinnedStackListenerForwarder.this.onConfigurationChanged(); - }); - } - - @Override public void onAspectRatioChanged(float aspectRatio) { mShellMainExecutor.execute(() -> { PinnedStackListenerForwarder.this.onAspectRatioChanged(aspectRatio); @@ -168,10 +141,6 @@ public class PinnedStackListenerForwarder { public void onActivityHidden(ComponentName componentName) {} - public void onDisplayInfoChanged(DisplayInfo displayInfo) {} - - public void onConfigurationChanged() {} - public void onAspectRatioChanged(float aspectRatio) {} } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java index da9ce0aacedc..1f07542c9a27 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java @@ -20,6 +20,7 @@ import android.annotation.Nullable; import android.app.PictureInPictureParams; import android.content.ComponentName; import android.content.pm.ActivityInfo; +import android.content.res.Configuration; import android.graphics.Rect; import com.android.wm.shell.common.annotations.ExternalThread; @@ -82,6 +83,12 @@ public interface Pip { } /** + * Called when configuration is changed. + */ + default void onConfigurationChanged(Configuration newConfig) { + } + + /** * Called when display size or font size of settings changed */ default void onDensityOrFontScaleChanged() { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java index b01961413fea..484592e87a20 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java @@ -102,9 +102,7 @@ public class PipBoundsAlgorithm { return mSnapAlgorithm; } - /** - * Responds to IPinnedStackListener on configuration change. - */ + /** Responds to configuration change. */ public void onConfigurationChanged(Context context) { reloadResources(context); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index 167b9f9975f3..9081783eeab8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -502,7 +502,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, mPipMenuController.attach(leash); - if (mShouldIgnoreEnteringPipTransition) { final Rect destinationBounds = mPipBoundsState.getBounds(); // animation is finished in the Launcher and here we directly apply the final touch. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index 9c7fdf761d3f..4d2760259521 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -33,6 +33,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.pm.ParceledListSlice; +import android.content.res.Configuration; import android.graphics.Rect; import android.os.RemoteException; import android.os.UserHandle; @@ -104,6 +105,9 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac // Skip if we aren't in PIP or haven't actually entered PIP yet. We still need to update // the display layout in the bounds handler in this case. onDisplayRotationChangedNotInPip(mContext, toRotation); + // do not forget to update the movement bounds as well. + updateMovementBounds(mPipBoundsState.getNormalBounds(), true /* fromRotation */, + false /* fromImeAdjustment */, false /* fromShelfAdjustment */, t); return; } // If there is an animation running (ie. from a shelf offset), then ensure that we calculate @@ -136,7 +140,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac } }; - private DisplayController.OnDisplaysChangedListener mFixedRotationListener = + private final DisplayController.OnDisplaysChangedListener mFixedRotationListener = new DisplayController.OnDisplaysChangedListener() { @Override public void onFixedRotationStarted(int displayId, int newRotation) { @@ -188,18 +192,6 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac } @Override - public void onDisplayInfoChanged(DisplayInfo displayInfo) { - mPipBoundsState.setDisplayInfo(displayInfo); - } - - @Override - public void onConfigurationChanged() { - mPipBoundsAlgorithm.onConfigurationChanged(mContext); - mTouchHandler.onConfigurationChanged(); - mPipBoundsState.onConfigurationChanged(); - } - - @Override public void onAspectRatioChanged(float aspectRatio) { // TODO(b/169373982): Remove this callback as it is redundant with PipTaskOrg params // change. @@ -334,6 +326,15 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac } @Override + public void onConfigurationChanged(Configuration newConfig) { + mMainExecutor.execute(() -> { + mPipBoundsAlgorithm.onConfigurationChanged(mContext); + mTouchHandler.onConfigurationChanged(); + mPipBoundsState.onConfigurationChanged(); + }); + } + + @Override public void onDensityOrFontScaleChanged() { mMainExecutor.execute(() -> { mPipTaskOrganizer.onDensityOrFontScaleChanged(mContext); @@ -532,7 +533,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac * * @return {@code true} if internal {@link DisplayInfo} is rotated, {@code false} otherwise. */ - public boolean onDisplayRotationChanged(Context context, Rect outBounds, Rect oldBounds, + private boolean onDisplayRotationChanged(Context context, Rect outBounds, Rect oldBounds, Rect outInsetBounds, int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) { // Bail early if the event is not sent to current {@link #mDisplayInfo} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java index 0649e58b9305..02f6231c6ecf 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java @@ -93,6 +93,7 @@ public class PipResizeGestureHandler { private int mDelta; private float mTouchSlop; + private boolean mAllowGesture; private boolean mIsAttached; private boolean mIsEnabled; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java index 9281f58f522f..33439a412b4d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java @@ -86,7 +86,7 @@ public class PipTouchHandler { private boolean mEnableStash = true; // The reference inset bounds, used to determine the dismiss fraction - private Rect mInsetBounds = new Rect(); + private final Rect mInsetBounds = new Rect(); private int mExpandedShortestEdgeSize; // Used to workaround an issue where the WM rotation happens before we are notified, allowing @@ -94,7 +94,8 @@ public class PipTouchHandler { private int mDeferResizeToNormalBoundsUntilRotation = -1; private int mDisplayRotation; - private Handler mHandler = new Handler(); + private final Handler mHandler = new Handler(); + private final PipAccessibilityInteractionConnection mConnection; // Behaviour states private int mMenuState = MENU_STATE_NONE; @@ -108,7 +109,6 @@ public class PipTouchHandler { private float mSavedSnapFraction = -1f; private boolean mSendingHoverAccessibilityEvents; private boolean mMovementWithinDismiss; - private PipAccessibilityInteractionConnection mConnection; // Touch state private final PipTouchState mTouchState; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java index 763370bec1c9..0955056900f1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java @@ -37,7 +37,6 @@ import android.content.IntentFilter; import android.content.pm.ParceledListSlice; import android.content.res.Configuration; import android.graphics.Rect; -import android.os.Debug; import android.os.Handler; import android.os.RemoteException; import android.os.UserHandle; @@ -56,8 +55,6 @@ import com.android.wm.shell.pip.PipBoundsState; import com.android.wm.shell.pip.PipMediaController; import com.android.wm.shell.pip.PipTaskOrganizer; -import java.util.ArrayList; -import java.util.List; import java.util.Objects; /** @@ -87,42 +84,21 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac private static final int TASK_ID_NO_PIP = -1; private static final int INVALID_RESOURCE_TYPE = -1; - public static final int SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH = 0x1; - - /** - * PIPed activity is playing a media and it can be paused. - */ - static final int PLAYBACK_STATE_PLAYING = 0; - /** - * PIPed activity has a paused media and it can be played. - */ - static final int PLAYBACK_STATE_PAUSED = 1; - /** - * Users are unable to control PIPed activity's media playback. - */ - static final int PLAYBACK_STATE_UNAVAILABLE = 2; - - private static final int CLOSE_PIP_WHEN_MEDIA_SESSION_GONE_TIMEOUT_MS = 3000; - - private int mSuspendPipResizingReason; - private final Context mContext; private final PipBoundsState mPipBoundsState; private final PipBoundsAlgorithm mPipBoundsAlgorithm; private final PipTaskOrganizer mPipTaskOrganizer; private final PipMediaController mPipMediaController; private final TvPipMenuController mTvPipMenuController; + private final PipNotification mPipNotification; private IActivityTaskManager mActivityTaskManager; private int mState = STATE_NO_PIP; - private int mResumeResizePinnedStackRunnableState = STATE_NO_PIP; private final Handler mHandler = new Handler(); - private List<Listener> mListeners = new ArrayList<>(); private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED; private int mPipTaskId = TASK_ID_NO_PIP; private int mPinnedStackId = INVALID_STACK_ID; private String[] mLastPackagesResourceGranted; - private PipNotification mPipNotification; private ParceledListSlice<RemoteAction> mCustomActions; private WindowManagerShellWrapper mWindowManagerShellWrapper; private int mResizeAnimationDuration; @@ -135,9 +111,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac private boolean mImeVisible; private int mImeHeightAdjustment; - private final Runnable mResizePinnedStackRunnable = - () -> resizePinnedStack(mResumeResizePinnedStackRunnableState); - private final Runnable mClosePipRunnable = () -> closePip(); + private final Runnable mClosePipRunnable = this::closePip; private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -237,8 +211,6 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac mPipTaskOrganizer.registerPipTransitionCallback(this); mActivityTaskManager = ActivityTaskManager.getService(); - addListener(mPipNotification); - final IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(ACTION_CLOSE); intentFilter.addAction(ACTION_MENU); @@ -297,6 +269,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac /** * Updates the PIP per configuration changed. */ + @Override public void onConfigurationChanged(Configuration newConfig) { loadConfigurationsAndApply(newConfig); mPipNotification.onConfigurationChanged(mContext); @@ -340,9 +313,8 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac mPinnedStackId = INVALID_STACK_ID; } } - for (int i = mListeners.size() - 1; i >= 0; --i) { - mListeners.get(i).onPipActivityClosed(); - } + mPipNotification.dismiss(); + mTvPipMenuController.hideMenu(); mHandler.removeCallbacks(mClosePipRunnable); } @@ -353,9 +325,9 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac if (DEBUG) Log.d(TAG, "movePipToFullscreen(), current state=" + getStateDescription()); mPipTaskId = TASK_ID_NO_PIP; - for (int i = mListeners.size() - 1; i >= 0; --i) { - mListeners.get(i).onMoveToFullscreen(); - } + mTvPipMenuController.hideMenu(); + mPipNotification.dismiss(); + resizePinnedStack(STATE_NO_PIP); } @@ -379,9 +351,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac // Set state to STATE_PIP so we show it when the pinned stack animation ends. mState = STATE_PIP; mPipMediaController.onActivityPinned(); - for (int i = mListeners.size() - 1; i >= 0; i--) { - mListeners.get(i).onPipEntered(packageName); - } + mPipNotification.show(packageName); } private void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task, @@ -428,61 +398,17 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac } /** - * Suspends resizing operation on the Pip until {@link #resumePipResizing} is called - * - * @param reason The reason for suspending resizing operations on the Pip. - */ - public void suspendPipResizing(int reason) { - if (DEBUG) { - Log.d(TAG, - "suspendPipResizing() reason=" + reason + " callers=" + Debug.getCallers(2)); - } - mSuspendPipResizingReason |= reason; - } - - /** - * Resumes resizing operation on the Pip that was previously suspended. - * - * @param reason The reason resizing operations on the Pip was suspended. - */ - public void resumePipResizing(int reason) { - if ((mSuspendPipResizingReason & reason) == 0) { - return; - } - if (DEBUG) { - Log.d(TAG, - "resumePipResizing() reason=" + reason + " callers=" + Debug.getCallers(2)); - } - mSuspendPipResizingReason &= ~reason; - mHandler.post(mResizePinnedStackRunnable); - } - - /** * Resize the Pip to the appropriate size for the input state. * * @param state In Pip state also used to determine the new size for the Pip. */ public void resizePinnedStack(int state) { - if (DEBUG) { Log.d(TAG, "resizePinnedStack() state=" + stateToName(state) + ", current state=" + getStateDescription(), new Exception()); } - - boolean wasStateNoPip = (mState == STATE_NO_PIP); - for (int i = mListeners.size() - 1; i >= 0; --i) { - mListeners.get(i).onPipResizeAboutToStart(); - } - if (mSuspendPipResizingReason != 0) { - mResumeResizePinnedStackRunnableState = state; - if (DEBUG) { - Log.d(TAG, "resizePinnedStack() deferring" - + " mSuspendPipResizingReason=" + mSuspendPipResizingReason - + " mResumeResizePinnedStackRunnableState=" - + stateToName(mResumeResizePinnedStackRunnableState)); - } - return; - } + final boolean wasStateNoPip = (mState == STATE_NO_PIP); + mTvPipMenuController.hideMenu(); mState = state; final Rect newBounds; switch (mState) { @@ -510,45 +436,20 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac } /** - * @return the current state, or the pending state if the state change was previously suspended. + * @return the current state. */ private int getState() { - if (mSuspendPipResizingReason != 0) { - return mResumeResizePinnedStackRunnableState; - } return mState; } - /** - * Shows PIP menu UI by launching {@link PipMenuActivity}. It also locates the pinned - * stack to the centered PIP bound {@link R.config_centeredPictureInPictureBounds}. - */ private void showPipMenu() { if (DEBUG) Log.d(TAG, "showPipMenu(), current state=" + getStateDescription()); mState = STATE_PIP_MENU; - for (int i = mListeners.size() - 1; i >= 0; --i) { - mListeners.get(i).onShowPipMenu(); - } - mTvPipMenuController.showMenu(); } /** - * Adds a {@link Listener} to PipController. - */ - void addListener(Listener listener) { - mListeners.add(listener); - } - - /** - * Removes a {@link Listener} from PipController. - */ - void removeListener(Listener listener) { - mListeners.remove(listener); - } - - /** * Returns {@code true} if PIP is shown. */ public boolean isPipShown() { @@ -619,33 +520,8 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac } } - /** - * A listener interface to receive notification on changes in PIP. - */ - public interface Listener { - /** - * Invoked when an activity is pinned and PIP manager is set corresponding information. - * Classes must use this instead of {@link android.app.ITaskStackListener.onActivityPinned} - * because there's no guarantee for the PIP manager be return relavent information - * correctly. (e.g. {@link Pip.isPipShown}). - */ - void onPipEntered(String packageName); - /** Invoked when a PIPed activity is closed. */ - void onPipActivityClosed(); - /** Invoked when the PIP menu gets shown. */ - void onShowPipMenu(); - /** Invoked when the PIPed activity is about to return back to the fullscreen. */ - void onMoveToFullscreen(); - /** Invoked when we are above to start resizing the Pip. */ - void onPipResizeAboutToStart(); - } - private String getStateDescription() { - if (mSuspendPipResizingReason == 0) { - return stateToName(mState); - } - return stateToName(mResumeResizePinnedStackRunnableState) + " (while " + stateToName(mState) - + " is suspended)"; + return stateToName(mState); } private static String stateToName(int state) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipMenuView.java index 689c3ede9efa..83cb7ce8065b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipMenuView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipMenuView.java @@ -16,6 +16,9 @@ package com.android.wm.shell.pip.tv; +import static android.view.KeyEvent.ACTION_UP; +import static android.view.KeyEvent.KEYCODE_BACK; + import android.animation.Animator; import android.animation.AnimatorInflater; import android.annotation.Nullable; @@ -36,25 +39,22 @@ import java.util.Collections; /** * The Menu View that shows controls of the PiP. Always fullscreen. */ -public class PipMenuView extends FrameLayout implements PipController.Listener { +public class PipMenuView extends FrameLayout { private static final String TAG = "PipMenuView"; private static final boolean DEBUG = PipController.DEBUG; - private final PipController mPipController; private final Animator mFadeInAnimation; private final Animator mFadeOutAnimation; private final PipControlsViewController mPipControlsViewController; - private boolean mRestorePipSizeWhenClose; + @Nullable + private OnBackPressListener mOnBackPressListener; public PipMenuView(Context context, PipController pipController) { super(context, null, 0); - mPipController = pipController; - inflate(context, R.layout.tv_pip_menu, this); mPipControlsViewController = new PipControlsViewController( - findViewById(R.id.pip_controls), mPipController); - mRestorePipSizeWhenClose = true; + findViewById(R.id.pip_controls), pipController); mFadeInAnimation = AnimatorInflater.loadAnimator( mContext, R.anim.tv_pip_menu_fade_in_animation); mFadeInAnimation.setTarget(mPipControlsViewController.getView()); @@ -63,16 +63,6 @@ public class PipMenuView extends FrameLayout implements PipController.Listener { mFadeOutAnimation.setTarget(mPipControlsViewController.getView()); } - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - if (event.getKeyCode() == KeyEvent.KEYCODE_BACK - && event.getAction() == KeyEvent.ACTION_UP) { - restorePipAndFinish(); - return true; - } - return super.dispatchKeyEvent(event); - } - @Nullable SurfaceControl getWindowSurfaceControl() { final ViewRootImpl root = getViewRootImpl(); @@ -87,53 +77,39 @@ public class PipMenuView extends FrameLayout implements PipController.Listener { } void showMenu() { - mPipController.addListener(this); mFadeInAnimation.start(); setAlpha(1.0f); - try { - WindowManagerGlobal.getWindowSession().grantEmbeddedWindowFocus(null /* window */, - getViewRootImpl().getInputToken(), true /* grantFocus */); - } catch (Exception e) { - Log.e(TAG, "Unable to update focus as menu appears", e); - } + grantWindowFocus(true); } void hideMenu() { - mPipController.removeListener(this); - mPipController.resumePipResizing( - PipController.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH); mFadeOutAnimation.start(); setAlpha(0.0f); + grantWindowFocus(false); + } + + private void grantWindowFocus(boolean grantFocus) { try { WindowManagerGlobal.getWindowSession().grantEmbeddedWindowFocus(null /* window */, - getViewRootImpl().getInputToken(), false /* grantFocus */); + getViewRootImpl().getInputToken(), grantFocus); } catch (Exception e) { Log.e(TAG, "Unable to update focus as menu disappears", e); } } - private void restorePipAndFinish() { - if (DEBUG) Log.d(TAG, "restorePipAndFinish()"); - - if (mRestorePipSizeWhenClose) { - if (DEBUG) Log.d(TAG, " > restoring to the default position"); - - // When PIP menu activity is closed, restore to the default position. - mPipController.resizePinnedStack(PipController.STATE_PIP); - } - hideMenu(); - } - - @Override - public void onPipEntered(String packageName) { - if (DEBUG) Log.d(TAG, "onPipEntered(), packageName=" + packageName); + void setOnBackPressListener(OnBackPressListener onBackPressListener) { + mOnBackPressListener = onBackPressListener; } @Override - public void onPipActivityClosed() { - if (DEBUG) Log.d(TAG, "onPipActivityClosed()"); - - hideMenu(); + public boolean dispatchKeyEvent(KeyEvent event) { + if (event.getKeyCode() == KEYCODE_BACK && event.getAction() == ACTION_UP + && mOnBackPressListener != null) { + mOnBackPressListener.onBackPress(); + return true; + } else { + return super.dispatchKeyEvent(event); + } } void setAppActions(ParceledListSlice<RemoteAction> actions) { @@ -144,27 +120,7 @@ public class PipMenuView extends FrameLayout implements PipController.Listener { hasCustomActions ? actions.getList() : Collections.emptyList()); } - @Override - public void onShowPipMenu() { - if (DEBUG) Log.d(TAG, "onShowPipMenu()"); - } - - @Override - public void onMoveToFullscreen() { - if (DEBUG) Log.d(TAG, "onMoveToFullscreen()"); - - // Moving PIP to fullscreen is implemented by resizing PINNED_STACK with null bounds. - // This conflicts with restoring PIP position, so disable it. - mRestorePipSizeWhenClose = false; - hideMenu(); - } - - @Override - public void onPipResizeAboutToStart() { - if (DEBUG) Log.d(TAG, "onPipResizeAboutToStart()"); - - hideMenu(); - mPipController.suspendPipResizing( - PipController.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH); + interface OnBackPressListener { + void onBackPress(); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java index d56a88874420..4e0ab668be81 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java @@ -39,7 +39,7 @@ import java.util.Objects; * <p>Once it's created, it will manage the PIP notification UI by itself except for handling * configuration changes. */ -public class PipNotification implements PipController.Listener { +public class PipNotification { private static final boolean DEBUG = PipController.DEBUG; private static final String TAG = "PipNotification"; @@ -79,38 +79,21 @@ public class PipNotification implements PipController.Listener { onConfigurationChanged(context); } - @Override - public void onPipEntered(String packageName) { + void show(String packageName) { mPackageName = packageName; - notifyPipNotification(); + update(); } - @Override - public void onPipActivityClosed() { - dismissPipNotification(); - mPackageName = null; - } - - @Override - public void onShowPipMenu() { - // no-op. - } - - @Override - public void onMoveToFullscreen() { - dismissPipNotification(); + void dismiss() { + mNotificationManager.cancel(NOTIFICATION_TAG, SystemMessage.NOTE_TV_PIP); + mNotified = false; mPackageName = null; } - @Override - public void onPipResizeAboutToStart() { - // no-op. - } - private void onMediaMetadataChanged(MediaMetadata metadata) { if (updateMediaControllerMetadata(metadata) && mNotified) { // update notification - notifyPipNotification(); + update(); } } @@ -123,11 +106,11 @@ public class PipNotification implements PipController.Listener { mDefaultIconResId = R.drawable.pip_icon; if (mNotified) { // update notification - notifyPipNotification(); + update(); } } - private void notifyPipNotification() { + private void update() { mNotified = true; mNotificationBuilder .setShowWhen(true) @@ -144,11 +127,6 @@ public class PipNotification implements PipController.Listener { mNotificationBuilder.build()); } - private void dismissPipNotification() { - mNotified = false; - mNotificationManager.cancel(NOTIFICATION_TAG, SystemMessage.NOTE_TV_PIP); - } - private boolean updateMediaControllerMetadata(MediaMetadata metadata) { String title = null; Bitmap art = null; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java index 91aef670b946..5d0d761abd93 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java @@ -21,6 +21,7 @@ import static android.view.WindowManager.SHELL_ROOT_LAYER_PIP; import android.app.RemoteAction; import android.content.Context; import android.content.pm.ParceledListSlice; +import android.util.Log; import android.view.SurfaceControl; import com.android.wm.shell.common.SystemWindows; @@ -31,6 +32,8 @@ import com.android.wm.shell.pip.PipMenuController; * Manages the visibility of the PiP Menu as user interacts with PiP. */ public class TvPipMenuController implements PipMenuController { + private static final String TAG = "TvPipMenuController"; + private static final boolean DEBUG = PipController.DEBUG; private final Context mContext; private final SystemWindows mSystemWindows; @@ -52,6 +55,8 @@ public class TvPipMenuController implements PipMenuController { @Override public void showMenu() { + if (DEBUG) Log.d(TAG, "showMenu()"); + if (mMenuView != null) { mSystemWindows.updateViewLayout(mMenuView, getPipMenuLayoutParams(MENU_WINDOW_TITLE, mPipBoundsState.getDisplayBounds().width(), @@ -68,27 +73,62 @@ public class TvPipMenuController implements PipMenuController { } } + void hideMenu() { + if (DEBUG) Log.d(TAG, "hideMenu()"); + + if (isMenuVisible()) { + mMenuView.hideMenu(); + mPipController.resizePinnedStack(PipController.STATE_PIP); + } + } + @Override public void attach(SurfaceControl leash) { - if (mMenuView == null) { - mMenuView = new PipMenuView(mContext, mPipController); - mSystemWindows.addView(mMenuView, - getPipMenuLayoutParams(MENU_WINDOW_TITLE, 0 /* width */, 0 /* height */), - 0, SHELL_ROOT_LAYER_PIP); - mLeash = leash; - } + mLeash = leash; + attachPipMenuView(); } @Override public void detach() { + hideMenu(); + detachPipMenuView(); + mLeash = null; + } + + private void attachPipMenuView() { + if (DEBUG) Log.d(TAG, "attachPipMenuView()"); + + if (mMenuView != null) { + detachPipMenuView(); + } + + mMenuView = new PipMenuView(mContext, mPipController); + mMenuView.setOnBackPressListener(this::hideMenu); + mSystemWindows.addView(mMenuView, + getPipMenuLayoutParams(MENU_WINDOW_TITLE, 0 /* width */, 0 /* height */), + 0, SHELL_ROOT_LAYER_PIP); + } + + private void detachPipMenuView() { + if (DEBUG) Log.d(TAG, "detachPipMenuView()"); + + if (mMenuView == null) { + return; + } + mSystemWindows.removeView(mMenuView); mMenuView = null; - mLeash = null; } @Override public void setAppActions(ParceledListSlice<RemoteAction> appActions) { - mMenuView.setAppActions(appActions); + if (DEBUG) Log.d(TAG, "setAppActions(), actions=" + appActions); + + if (mMenuView != null) { + mMenuView.setAppActions(appActions); + } else { + Log.w(TAG, "Cannot set remote actions, there is no View"); + } } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java index f2becc99eae8..5078371dab64 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java @@ -24,6 +24,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static android.view.WindowManager.SHELL_ROOT_LAYER_DIVIDER; @@ -59,7 +60,7 @@ final class DividerWindowManager { PixelFormat.TRANSLUCENT); mLp.token = new Binder(); mLp.setTitle(WINDOW_TITLE); - mLp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION; + mLp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY; mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java index 5b2b38ba8189..af451ae8bc50 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java @@ -205,12 +205,9 @@ class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener { private void updateChildTaskSurface( RunningTaskInfo taskInfo, SurfaceControl leash, boolean firstAppeared) { - final Rect taskBounds = taskInfo.getConfiguration().windowConfiguration.getBounds(); final Point taskPositionInParent = taskInfo.positionInParent; - final Rect corp = new Rect(taskBounds); - corp.offset(-taskBounds.left, -taskBounds.top); mSyncQueue.runInSync(t -> { - t.setWindowCrop(leash, corp); + t.setWindowCrop(leash, null); t.setPosition(leash, taskPositionInParent.x, taskPositionInParent.y); if (firstAppeared && !Transitions.ENABLE_SHELL_TRANSITIONS) { t.setAlpha(leash, 1f); diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt index 3ed53fb221a7..1638d72f9914 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt @@ -25,7 +25,7 @@ fun LayersAssertion.appPairsDividerIsVisible( enabled: Boolean = bugId == 0 ) { end("appPairsDividerIsVisible", bugId, enabled) { - this.showsLayer(FlickerTestBase.APP_PAIRS_DIVIDER) + this.showsLayer(FlickerTestBase.SPLIT_DIVIDER) } } @@ -35,7 +35,7 @@ fun LayersAssertion.appPairsDividerIsInvisible( enabled: Boolean = bugId == 0 ) { end("appPairsDividerIsInVisible", bugId, enabled) { - this.hasNotLayer(FlickerTestBase.APP_PAIRS_DIVIDER) + this.hasNotLayer(FlickerTestBase.SPLIT_DIVIDER) } } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt index 54b8fdc83a1f..7809be04de96 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt @@ -130,7 +130,7 @@ abstract class FlickerTestBase { const val NAVIGATION_BAR_WINDOW_TITLE = "NavigationBar" const val STATUS_BAR_WINDOW_TITLE = "StatusBar" const val DOCKED_STACK_DIVIDER = "DockedStackDivider" - const val APP_PAIRS_DIVIDER = "AppPairDivider" + const val SPLIT_DIVIDER = "SplitDivider" const val IMAGE_WALLPAPER = "ImageWallpaper" } } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt index 7ac91b065fca..0f8d30a94ec6 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt @@ -108,7 +108,7 @@ class AppPairsTest( end("appsEndingBounds", enabled = false) { val entry = this.trace.entries.firstOrNull() ?: throw IllegalStateException("Trace is empty") - val dividerRegion = entry.getVisibleBounds(APP_PAIRS_DIVIDER) + val dividerRegion = entry.getVisibleBounds(SPLIT_DIVIDER) this.hasVisibleRegion(primaryApp.defaultWindowName, appPairsHelper.getPrimaryBounds(dividerRegion)) .and() @@ -152,7 +152,7 @@ class AppPairsTest( start("appsStartingBounds", enabled = false) { val entry = this.trace.entries.firstOrNull() ?: throw IllegalStateException("Trace is empty") - val dividerRegion = entry.getVisibleBounds(APP_PAIRS_DIVIDER) + val dividerRegion = entry.getVisibleBounds(SPLIT_DIVIDER) this.hasVisibleRegion(primaryApp.defaultWindowName, appPairsHelper.getPrimaryBounds(dividerRegion)) .and() diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxTaskListenerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxTaskListenerTest.java index fc0e20b553d3..5cbc7d927d61 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxTaskListenerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxTaskListenerTest.java @@ -99,7 +99,8 @@ public final class LetterboxTaskListenerTest extends ShellTestCase { /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds /* parentBounds */ new Rect(0, 0, 200, 100), /* activityBounds */ new Rect(75, 0, 125, 75), - /* taskBounds */ new Rect(50, 0, 125, 100)), + /* taskBounds */ new Rect(50, 0, 125, 100), + /* activityInsets */ new Rect(0, 0, 0, 0)), mLeash); // Task doesn't need to repositioned @@ -114,7 +115,8 @@ public final class LetterboxTaskListenerTest extends ShellTestCase { /* parentBounds */ new Rect(0, 0, 200, 100), // Activity is offset by 25 to the left /* activityBounds */ new Rect(50, 0, 100, 75), - /* taskBounds */ new Rect(50, 0, 125, 100))); + /* taskBounds */ new Rect(50, 0, 125, 100), + /* activityInsets */ new Rect(0, 0, 0, 0))); // Task needs to be repositioned by 25 to the left verifySetPosition(75, 0); @@ -135,7 +137,8 @@ public final class LetterboxTaskListenerTest extends ShellTestCase { /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds /* parentBounds */ new Rect(0, 0, 200, 100), /* activityBounds */ new Rect(150, 0, 200, 75), - /* taskBounds */ new Rect(125, 0, 200, 100)), + /* taskBounds */ new Rect(125, 0, 200, 100), + /* activityInsets */ new Rect(0, 10, 10, 0)), mLeash); verifySetPosition(-15, 0); @@ -156,7 +159,8 @@ public final class LetterboxTaskListenerTest extends ShellTestCase { /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds /* parentBounds */ new Rect(0, 0, 200, 100), /* activityBounds */ new Rect(150, 0, 200, 75), - /* taskBounds */ new Rect(125, 0, 200, 100)), + /* taskBounds */ new Rect(125, 0, 200, 100), + /* activityInsets */ new Rect(0, 10, 10, 0)), mLeash); verifySetPosition(55, 0); @@ -177,7 +181,8 @@ public final class LetterboxTaskListenerTest extends ShellTestCase { /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds /* parentBounds */ new Rect(0, 0, 200, 100), /* activityBounds */ new Rect(50, 0, 100, 75), - /* taskBounds */ new Rect(25, 0, 100, 100)), + /* taskBounds */ new Rect(25, 0, 100, 100), + /* activityInsets */ new Rect(0, 10, 10, 0)), mLeash); verifySetPosition(115, 0); @@ -198,7 +203,8 @@ public final class LetterboxTaskListenerTest extends ShellTestCase { /* maxBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds /* parentBounds */ new Rect(0, 0, 100, 150), /* activityBounds */ new Rect(0, 75, 50, 125), - /* taskBounds */ new Rect(0, 50, 100, 125)), + /* taskBounds */ new Rect(0, 50, 100, 125), + /* activityInsets */ new Rect(10, 0, 0, 0)), mLeash); verifySetPosition(20, -15); @@ -219,7 +225,8 @@ public final class LetterboxTaskListenerTest extends ShellTestCase { /* maxBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds /* parentBounds */ new Rect(0, 0, 100, 150), /* activityBounds */ new Rect(0, 75, 50, 125), - /* taskBounds */ new Rect(0, 50, 100, 125)), + /* taskBounds */ new Rect(0, 50, 100, 125), + /* activityInsets */ new Rect(10, 0, 0, 0)), mLeash); verifySetPosition(20, 20); @@ -228,6 +235,29 @@ public final class LetterboxTaskListenerTest extends ShellTestCase { } @Test + public void testOnTaskInfoAppeared_portraitWithCenterGravity_visibleLeftInset() { + mLetterboxConfigController.setPortraitGravity(Gravity.CENTER); + setWindowBoundsAndInsets( + /* windowBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds + Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 20)); + + mLetterboxTaskListener.onTaskAppeared( + createTaskInfo( + /* taskId */ 1, + /* maxBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds + /* parentBounds */ new Rect(0, 0, 100, 150), + /* activityBounds */ new Rect(0, 75, 50, 125), + /* taskBounds */ new Rect(0, 50, 100, 125), + // Activity is drawn under the left inset. + /* activityInsets */ new Rect(0, 0, 0, 0)), + mLeash); + + verifySetPosition(20, 20); + // Should return activity coordinates offset by task coordinates + verifySetWindowCrop(new Rect(0, 25, 50, 75)); + } + + @Test public void testOnTaskInfoAppeared_portraitWithBottomGravity() { mLetterboxConfigController.setPortraitGravity(Gravity.BOTTOM); setWindowBoundsAndInsets( @@ -240,7 +270,8 @@ public final class LetterboxTaskListenerTest extends ShellTestCase { /* maxBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds /* parentBounds */ new Rect(0, 0, 100, 150), /* activityBounds */ new Rect(0, 75, 50, 125), - /* taskBounds */ new Rect(0, 50, 100, 125)), + /* taskBounds */ new Rect(0, 50, 100, 125), + /* activityInsets */ new Rect(10, 0, 0, 0)), mLeash); verifySetPosition(20, 55); @@ -261,14 +292,14 @@ public final class LetterboxTaskListenerTest extends ShellTestCase { /* maxBounds= */ new Rect(0, 0, 200, 125), // equal to parent bounds /* parentBounds */ new Rect(0, 0, 200, 125), /* activityBounds */ new Rect(15, 0, 175, 120), - /* taskBounds */ new Rect(0, 0, 100, 125)), // equal to parent bounds + /* taskBounds */ new Rect(0, 0, 200, 125), + /* activityInsets */ new Rect(10, 25, 10, 10)), // equal to parent bounds mLeash); // Activity fully covers parent bounds with insets so doesn't need to be moved. verifySetPosition(0, 0); - // Should return activity coordinates offset by task coordinates minus all insets - // except top one (keep status bar decor visible). - verifySetWindowCrop(new Rect(25, 0, 165, 110)); + // Should return activity coordinates offset by task coordinates + verifySetWindowCrop(new Rect(15, 0, 175, 120)); } @Test @@ -284,7 +315,8 @@ public final class LetterboxTaskListenerTest extends ShellTestCase { /* maxBounds= */ new Rect(0, 0, 100, 150), /* parentBounds */ new Rect(0, 75, 100, 225), /* activityBounds */ new Rect(25, 75, 75, 125), - /* taskBounds */ new Rect(0, 75, 100, 125)), + /* taskBounds */ new Rect(0, 75, 100, 125), + /* activityInsets */ new Rect(10, 0, 0, 0)), mLeash); verifySetPosition(0, 0); @@ -295,7 +327,8 @@ public final class LetterboxTaskListenerTest extends ShellTestCase { public void testOnTaskAppeared_calledSecondTimeWithSameTaskId_throwsException() { setWindowBoundsAndInsets(new Rect(), Insets.NONE); RunningTaskInfo taskInfo = - createTaskInfo(/* taskId */ 1, new Rect(), new Rect(), new Rect(), new Rect()); + createTaskInfo(/* taskId */ 1, new Rect(), new Rect(), new Rect(), new Rect(), + new Rect()); mLetterboxTaskListener.onTaskAppeared(taskInfo, mLeash); mLetterboxTaskListener.onTaskAppeared(taskInfo, mLeash); } @@ -319,13 +352,15 @@ public final class LetterboxTaskListenerTest extends ShellTestCase { final Rect maxBounds, final Rect parentBounds, final Rect activityBounds, - final Rect taskBounds) { + final Rect taskBounds, + final Rect activityInsets) { RunningTaskInfo taskInfo = new RunningTaskInfo(); taskInfo.taskId = taskId; taskInfo.configuration.windowConfiguration.setMaxBounds(maxBounds); taskInfo.parentBounds = parentBounds; taskInfo.configuration.windowConfiguration.setBounds(taskBounds); taskInfo.letterboxActivityBounds = Rect.copyOrNull(activityBounds); + taskInfo.letterboxActivityInsets = Rect.copyOrNull(activityInsets); return taskInfo; } diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h index 738246d56d0d..ee7d15a2fbce 100644 --- a/libs/hwui/FrameInfo.h +++ b/libs/hwui/FrameInfo.h @@ -159,7 +159,7 @@ public: // GPU start time is approximated to the moment before swapBuffer is invoked. // We could add an EGLSyncKHR fence at the beginning of the frame, but that is an overhead. int64_t endTime = get(FrameInfoIndex::GpuCompleted); - return endTime > 0 ? endTime - get(FrameInfoIndex::SwapBuffers) : 0; + return endTime > 0 ? endTime - get(FrameInfoIndex::SwapBuffers) : -1; } inline int64_t& set(FrameInfoIndex index) { return mFrameInfo[static_cast<int>(index)]; } diff --git a/libs/incident/OWNERS b/libs/incident/OWNERS new file mode 100644 index 000000000000..f76611555dbb --- /dev/null +++ b/libs/incident/OWNERS @@ -0,0 +1 @@ +include /cmds/incidentd/OWNERS diff --git a/libs/input/OWNERS b/libs/input/OWNERS new file mode 100644 index 000000000000..d701f23cb9b8 --- /dev/null +++ b/libs/input/OWNERS @@ -0,0 +1 @@ +include /core/java/android/hardware/input/OWNERS diff --git a/libs/storage/OWNERS b/libs/storage/OWNERS new file mode 100644 index 000000000000..6f9dbea36b06 --- /dev/null +++ b/libs/storage/OWNERS @@ -0,0 +1 @@ +include /core/java/android/os/storage/OWNERS diff --git a/libs/usb/OWNERS b/libs/usb/OWNERS new file mode 100644 index 000000000000..f7b2a37a297a --- /dev/null +++ b/libs/usb/OWNERS @@ -0,0 +1 @@ +include /services/usb/OWNERS diff --git a/location/OWNERS b/location/OWNERS new file mode 100644 index 000000000000..5ac6028411f0 --- /dev/null +++ b/location/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/location/OWNERS diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index d3dc3b32e15d..92e213609d4a 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -30,6 +30,7 @@ import android.location.IGnssStatusListener; import android.location.IGnssNavigationMessageListener; import android.location.ILocationCallback; import android.location.ILocationListener; +import android.location.LastLocationRequest; import android.location.Location; import android.location.LocationRequest; import android.location.LocationTime; @@ -45,7 +46,7 @@ import com.android.internal.location.ProviderProperties; */ interface ILocationManager { - @nullable Location getLastLocation(String provider, String packageName, String attributionTag); + @nullable Location getLastLocation(String provider, in LastLocationRequest request, String packageName, String attributionTag); @nullable ICancellationSignal getCurrentLocation(String provider, in LocationRequest request, in ILocationCallback callback, String packageName, String attributionTag, String listenerId); void registerLocationListener(String provider, in LocationRequest request, in ILocationListener listener, String packageName, String attributionTag, String listenerId); diff --git a/location/java/android/location/LastLocationRequest.aidl b/location/java/android/location/LastLocationRequest.aidl new file mode 100644 index 000000000000..30c90a9a47bd --- /dev/null +++ b/location/java/android/location/LastLocationRequest.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2012, 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.location; + +parcelable LastLocationRequest; diff --git a/location/java/android/location/LastLocationRequest.java b/location/java/android/location/LastLocationRequest.java new file mode 100644 index 000000000000..9ea8048ad476 --- /dev/null +++ b/location/java/android/location/LastLocationRequest.java @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.location; + +import android.Manifest; +import android.annotation.NonNull; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * An encapsulation of various parameters for requesting last location via {@link LocationManager}. + * + * @hide + */ +@SystemApi +public final class LastLocationRequest implements Parcelable { + + private final boolean mHiddenFromAppOps; + private final boolean mLocationSettingsIgnored; + + private LastLocationRequest( + boolean hiddenFromAppOps, + boolean locationSettingsIgnored) { + mHiddenFromAppOps = hiddenFromAppOps; + mLocationSettingsIgnored = locationSettingsIgnored; + } + + /** + * Returns true if this last location request should be ignored while updating app ops with + * location usage. This implies that someone else (usually the creator of the last location + * request) is responsible for updating app ops. + * + * @return true if this request should be ignored while updating app ops with location usage + * + */ + public boolean isHiddenFromAppOps() { + return mHiddenFromAppOps; + } + + /** + * Returns true if location settings, throttling, background location limits, and any other + * possible limiting factors will be ignored in order to satisfy this last location request. + * + * @return true if all limiting factors will be ignored to satisfy this request + */ + public boolean isLocationSettingsIgnored() { + return mLocationSettingsIgnored; + } + + public static final @NonNull Parcelable.Creator<LastLocationRequest> CREATOR = + new Parcelable.Creator<LastLocationRequest>() { + @Override + public LastLocationRequest createFromParcel(Parcel in) { + return new LastLocationRequest( + /* hiddenFromAppOps= */ in.readBoolean(), + /* locationSettingsIgnored= */ in.readBoolean()); + } + @Override + public LastLocationRequest[] newArray(int size) { + return new LastLocationRequest[size]; + } + }; + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel parcel, int flags) { + parcel.writeBoolean(mHiddenFromAppOps); + parcel.writeBoolean(mLocationSettingsIgnored); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + LastLocationRequest that = (LastLocationRequest) o; + return mHiddenFromAppOps == that.mHiddenFromAppOps + && mLocationSettingsIgnored == that.mLocationSettingsIgnored; + } + + @Override + public int hashCode() { + return Objects.hash(mHiddenFromAppOps, mLocationSettingsIgnored); + } + + @NonNull + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append("LastLocationRequest["); + if (mHiddenFromAppOps) { + s.append("hiddenFromAppOps, "); + } + if (mLocationSettingsIgnored) { + s.append("locationSettingsIgnored, "); + } + if (s.length() > "LastLocationRequest[".length()) { + s.setLength(s.length() - 2); + } + s.append(']'); + return s.toString(); + } + + /** + * A builder class for {@link LastLocationRequest}. + */ + public static final class Builder { + + private boolean mHiddenFromAppOps; + private boolean mLocationSettingsIgnored; + + /** + * Creates a new Builder. + */ + public Builder() { + mHiddenFromAppOps = false; + mLocationSettingsIgnored = false; + } + + /** + * Creates a new Builder with all parameters copied from the given last location request. + */ + public Builder(@NonNull LastLocationRequest lastLocationRequest) { + mHiddenFromAppOps = lastLocationRequest.mHiddenFromAppOps; + mLocationSettingsIgnored = lastLocationRequest.mLocationSettingsIgnored; + } + + /** + * If set to true, indicates that app ops should not be updated with location usage due to + * this request. This implies that someone else (usually the creator of the last location + * request) is responsible for updating app ops as appropriate. Defaults to false. + * + * <p>Permissions enforcement occurs when resulting last location request is actually used, + * not when this method is invoked. + */ + @RequiresPermission(Manifest.permission.UPDATE_APP_OPS_STATS) + public @NonNull Builder setHiddenFromAppOps(boolean hiddenFromAppOps) { + mHiddenFromAppOps = hiddenFromAppOps; + return this; + } + + /** + * If set to true, indicates that location settings, throttling, background location limits, + * and any other possible limiting factors should be ignored in order to satisfy this + * last location request. This is only intended for use in user initiated emergency + * situations, and should be used extremely cautiously. Defaults to false. + * + * <p>Permissions enforcement occurs when resulting last location request is actually used, + * not when this method is invoked. + */ + @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) + public @NonNull Builder setLocationSettingsIgnored(boolean locationSettingsIgnored) { + mLocationSettingsIgnored = locationSettingsIgnored; + return this; + } + + /** + * Builds a last location request from this builder. + * + * @return a new last location request + */ + public @NonNull LastLocationRequest build() { + return new LastLocationRequest( + mHiddenFromAppOps, + mLocationSettingsIgnored); + } + } +} diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java index b4392b1d29b4..47ecbd80a07f 100644 --- a/location/java/android/location/Location.java +++ b/location/java/android/location/Location.java @@ -19,6 +19,7 @@ package android.location; import static java.util.concurrent.TimeUnit.NANOSECONDS; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; @@ -1066,7 +1067,7 @@ public class Location implements Parcelable { * @deprecated Do not use. */ @Deprecated - public void setExtras(Bundle extras) { + public void setExtras(@Nullable Bundle extras) { mExtras = (extras == null) ? null : new Bundle(extras); } diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 604c4a1de8f9..7085a755990f 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -683,6 +683,7 @@ public class LocationManager { * location should always be checked. * * @return the last known location, or null if not available + * * @throws SecurityException if no suitable location permission is present * * @hide @@ -706,18 +707,50 @@ public class LocationManager { * in the course of the attempt as compared to this method. * * @param provider a provider listed by {@link #getAllProviders()} + * * @return the last known location for the given provider, or null if not available + * * @throws SecurityException if no suitable permission is present * @throws IllegalArgumentException if provider is null or doesn't exist */ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) @Nullable public Location getLastKnownLocation(@NonNull String provider) { + return getLastKnownLocation(provider, new LastLocationRequest.Builder().build()); + } + + /** + * Gets the last known location from the given provider, or null if there is no last known + * location. + * + * <p>See {@link LastLocationRequest} documentation for an explanation of various request + * parameters and how they can affect the returned location. + * + * <p>See {@link #getLastKnownLocation(String)} for more detail on how this method works. + * + * @param provider a provider listed by {@link #getAllProviders()} + * @param lastLocationRequest the last location request containing location parameters + * + * @return the last known location for the given provider, or null if not available + * + * @throws SecurityException if no suitable permission is present + * @throws IllegalArgumentException if provider is null or doesn't exist + * @throws IllegalArgumentException if lastLocationRequest is null + * + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) + @Nullable + public Location getLastKnownLocation(@NonNull String provider, + @NonNull LastLocationRequest lastLocationRequest) { Preconditions.checkArgument(provider != null, "invalid null provider"); + Preconditions.checkArgument(lastLocationRequest != null, + "invalid null last location request"); try { - return mService.getLastLocation(provider, mContext.getPackageName(), - mContext.getAttributionTag()); + return mService.getLastLocation(provider, lastLocationRequest, + mContext.getPackageName(), mContext.getAttributionTag()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/location/java/android/location/OWNERS b/location/java/android/location/OWNERS new file mode 100644 index 000000000000..383321bc3d69 --- /dev/null +++ b/location/java/android/location/OWNERS @@ -0,0 +1,6 @@ +# Bug component: 880425 + +mstogaitis@google.com +wyattriley@google.com +etn@google.com +weiwa@google.com diff --git a/media/OWNERS b/media/OWNERS index e74149019b11..b2875e7f067c 100644 --- a/media/OWNERS +++ b/media/OWNERS @@ -10,7 +10,7 @@ insun@google.com jaewan@google.com jinpark@google.com jmtrivi@google.com -jsharkey@android.com +jsharkey@google.com klhyun@google.com lajos@google.com marcone@google.com diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java index b67851a6b64f..2a3704df77db 100644 --- a/media/java/android/media/AudioDeviceInfo.java +++ b/media/java/android/media/AudioDeviceInfo.java @@ -23,6 +23,7 @@ import android.util.SparseIntArray; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; +import java.util.List; import java.util.Objects; import java.util.TreeSet; @@ -498,6 +499,13 @@ public final class AudioDeviceInfo { } /** + * @return A list of {@link AudioProfile} supported by the audio devices. + */ + public @NonNull List<AudioProfile> getAudioProfiles() { + return mPort.profiles(); + } + + /** * Returns an array of supported encapsulation modes for the device. * * The array can include any of the {@code AudioTrack} encapsulation modes, diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java index 0f79675862c7..9c42bf7e5605 100644 --- a/media/java/android/media/AudioDevicePort.java +++ b/media/java/android/media/AudioDevicePort.java @@ -21,6 +21,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import java.util.Arrays; +import java.util.List; /** * The AudioDevicePort is a specialized type of AudioPort @@ -57,6 +58,18 @@ public class AudioDevicePort extends AudioPort { mEncapsulationMetadataTypes = encapsulationMetadataTypes; } + AudioDevicePort(AudioHandle handle, String deviceName, List<AudioProfile> profiles, + AudioGain[] gains, int type, String address, int[] encapsulationModes, + @AudioTrack.EncapsulationMetadataType int[] encapsulationMetadataTypes) { + super(handle, + AudioManager.isInputDevice(type) ? AudioPort.ROLE_SOURCE : AudioPort.ROLE_SINK, + deviceName, profiles, gains); + mType = type; + mAddress = address; + mEncapsulationModes = encapsulationModes; + mEncapsulationMetadataTypes = encapsulationMetadataTypes; + } + /** * Get the device type (e.g AudioManager.DEVICE_OUT_SPEAKER) */ diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 457888361f73..c67d90a5ea0f 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -2881,7 +2881,12 @@ public class AudioManager { * @return true if any music tracks are active. */ public boolean isMusicActive() { - return AudioSystem.isStreamActive(STREAM_MUSIC, 0); + final IAudioService service = getService(); + try { + return service.isMusicActive(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** diff --git a/media/java/android/media/AudioMixPort.java b/media/java/android/media/AudioMixPort.java index 0e286b0f1f89..7f2249d05ec2 100644 --- a/media/java/android/media/AudioMixPort.java +++ b/media/java/android/media/AudioMixPort.java @@ -19,6 +19,8 @@ package android.media; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; +import java.util.List; + /** * The AudioMixPort is a specialized type of AudioPort * describing an audio mix or stream at an input or output stream of the audio @@ -42,6 +44,12 @@ public class AudioMixPort extends AudioPort { mIoHandle = ioHandle; } + AudioMixPort(AudioHandle handle, int ioHandle, int role, String deviceName, + List<AudioProfile> profiles, AudioGain[] gains) { + super(handle, role, deviceName, profiles, gains); + mIoHandle = ioHandle; + } + /** * Build a specific configuration of this audio mix port for use by methods * like AudioManager.connectAudioPatch(). diff --git a/media/java/android/media/AudioPlaybackConfiguration.java b/media/java/android/media/AudioPlaybackConfiguration.java index 515e9d0d4c5c..17305a501cd0 100644 --- a/media/java/android/media/AudioPlaybackConfiguration.java +++ b/media/java/android/media/AudioPlaybackConfiguration.java @@ -89,9 +89,8 @@ public final class AudioPlaybackConfiguration implements Parcelable { /** * @hide * Player backed an AAudio player. - * Note this type is not in System API so it will not be returned in public API calls */ - // TODO unhide for SystemApi, update getPlayerType() + @SystemApi public static final int PLAYER_TYPE_AAUDIO = 13; /** @@ -280,10 +279,7 @@ public final class AudioPlaybackConfiguration implements Parcelable { /** * @hide - * Return the type of player linked to this configuration. The return value is one of - * {@link #PLAYER_TYPE_JAM_AUDIOTRACK}, {@link #PLAYER_TYPE_JAM_MEDIAPLAYER}, - * {@link #PLAYER_TYPE_JAM_SOUNDPOOL}, {@link #PLAYER_TYPE_SLES_AUDIOPLAYER_BUFFERQUEUE}, - * {@link #PLAYER_TYPE_SLES_AUDIOPLAYER_URI_FD}, or {@link #PLAYER_TYPE_UNKNOWN}. + * Return the type of player linked to this configuration. * <br>Note that player types not exposed in the system API will be represented as * {@link #PLAYER_TYPE_UNKNOWN}. * @return the type of the player. @@ -291,7 +287,6 @@ public final class AudioPlaybackConfiguration implements Parcelable { @SystemApi public @PlayerType int getPlayerType() { switch (mPlayerType) { - case PLAYER_TYPE_AAUDIO: case PLAYER_TYPE_HW_SOURCE: case PLAYER_TYPE_EXTERNAL_PROXY: return PLAYER_TYPE_UNKNOWN; diff --git a/media/java/android/media/AudioPort.java b/media/java/android/media/AudioPort.java index e6dc622a11c1..03022501fbca 100644 --- a/media/java/android/media/AudioPort.java +++ b/media/java/android/media/AudioPort.java @@ -19,6 +19,13 @@ package android.media; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + /** * An audio port is a node of the audio framework or hardware that can be connected to or * disconnect from another audio node to create a specific audio routing configuration. @@ -78,6 +85,7 @@ public class AudioPort { private final int[] mChannelMasks; private final int[] mChannelIndexMasks; private final int[] mFormats; + private final List<AudioProfile> mProfiles; @UnsupportedAppUsage private final AudioGain[] mGains; @UnsupportedAppUsage @@ -87,7 +95,6 @@ public class AudioPort { AudioPort(AudioHandle handle, int role, String name, int[] samplingRates, int[] channelMasks, int[] channelIndexMasks, int[] formats, AudioGain[] gains) { - mHandle = handle; mRole = role; mName = name; @@ -96,6 +103,39 @@ public class AudioPort { mChannelIndexMasks = channelIndexMasks; mFormats = formats; mGains = gains; + mProfiles = new ArrayList<>(); + if (mFormats != null) { + for (int format : mFormats) { + mProfiles.add(new AudioProfile( + format, samplingRates, channelMasks, channelIndexMasks)); + } + } + } + + AudioPort(AudioHandle handle, int role, String name, + List<AudioProfile> profiles, AudioGain[] gains) { + mHandle = handle; + mRole = role; + mName = name; + mProfiles = profiles; + mGains = gains; + Set<Integer> formats = new HashSet<>(); + Set<Integer> samplingRates = new HashSet<>(); + Set<Integer> channelMasks = new HashSet<>(); + Set<Integer> channelIndexMasks = new HashSet<>(); + for (AudioProfile profile : profiles) { + formats.add(profile.getFormat()); + samplingRates.addAll(Arrays.stream(profile.getSampleRates()).boxed() + .collect(Collectors.toList())); + channelMasks.addAll(Arrays.stream(profile.getChannelMasks()).boxed() + .collect(Collectors.toList())); + channelIndexMasks.addAll(Arrays.stream(profile.getChannelIndexMasks()).boxed() + .collect(Collectors.toList())); + } + mSamplingRates = samplingRates.stream().mapToInt(Number::intValue).toArray(); + mChannelMasks = channelMasks.stream().mapToInt(Number::intValue).toArray(); + mChannelIndexMasks = channelIndexMasks.stream().mapToInt(Number::intValue).toArray(); + mFormats = formats.stream().mapToInt(Number::intValue).toArray(); } AudioHandle handle() { @@ -163,6 +203,13 @@ public class AudioPort { } /** + * Get the list of supported audio profiles + */ + public List<AudioProfile> profiles() { + return mProfiles; + } + + /** * Get the list of gain descriptors * Empty array if this port does not have gain control */ diff --git a/media/java/android/media/AudioProfile.java b/media/java/android/media/AudioProfile.java new file mode 100644 index 000000000000..42041667476a --- /dev/null +++ b/media/java/android/media/AudioProfile.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +import android.annotation.NonNull; + +/** + * AudioProfile is a class used by {@link AudioDeviceInfo} to list the audio formats, sampling rates + * and channel masks supported. + * Each AudioProfile is specific to an audio format and lists all sampling rates and channel masks + * supported for this format. + */ +public class AudioProfile { + private final int mFormat; + private final int[] mSamplingRates; + private final int[] mChannelMasks; + private final int[] mChannelIndexMasks; + + AudioProfile(int format, @NonNull int[] samplingRates, @NonNull int[] channelMasks, + @NonNull int[] channelIndexMasks) { + mFormat = format; + mSamplingRates = samplingRates; + mChannelMasks = channelMasks; + mChannelIndexMasks = channelIndexMasks; + } + + /** + * @return the encoding format for this AudioProfile. + */ + public @AudioFormat.Encoding int getFormat() { + return mFormat; + } + + /** + * @return an array of channel position masks that are associated with the encoding format. + */ + public @NonNull int[] getChannelMasks() { + return mChannelMasks; + } + + /** + * @return an array of channel index masks that are associated with the encoding format. + */ + public @NonNull int[] getChannelIndexMasks() { + return mChannelIndexMasks; + } + + /** + * @return an array of sample rates that are associated with the encoding format. + */ + public @NonNull int[] getSampleRates() { + return mSamplingRates; + } +} diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 5c012bef9a68..2ac5b5088d98 100755 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -334,4 +334,6 @@ interface IAudioService { oneway void setStreamVolumeForUid(int streamType, int direction, int flags, in String packageName, int uid, int pid, in UserHandle userHandle, int targetSdkVersion); + + boolean isMusicActive(); } diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java index a17ff825e21b..babc1d58b1a8 100644 --- a/media/java/android/media/MediaHTTPConnection.java +++ b/media/java/android/media/MediaHTTPConnection.java @@ -19,7 +19,7 @@ package android.media; import static android.media.MediaPlayer.MEDIA_ERROR_UNSUPPORTED; import android.compat.annotation.UnsupportedAppUsage; -import android.net.NetworkUtils; +import android.net.InetAddresses; import android.os.IBinder; import android.os.StrictMode; import android.util.Log; @@ -214,7 +214,7 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub { if (host.equalsIgnoreCase("localhost")) { return true; } - if (NetworkUtils.numericToInetAddress(host).isLoopbackAddress()) { + if (InetAddresses.parseNumericAddress(host).isLoopbackAddress()) { return true; } } catch (IllegalArgumentException iex) { diff --git a/media/java/android/media/OWNERS b/media/java/android/media/OWNERS new file mode 100644 index 000000000000..cbc9ab7e4adf --- /dev/null +++ b/media/java/android/media/OWNERS @@ -0,0 +1,8 @@ +# Bug component: 1344 + +fgoldfain@google.com +elaurent@google.com +lajos@google.com +olly@google.com +andrewlewis@google.com +sungsoo@google.com diff --git a/media/java/android/media/audiofx/OWNERS b/media/java/android/media/audiofx/OWNERS new file mode 100644 index 000000000000..189fe0f04da8 --- /dev/null +++ b/media/java/android/media/audiofx/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 48436 + +elaurent@google.com diff --git a/media/java/android/media/audiopolicy/OWNERS b/media/java/android/media/audiopolicy/OWNERS new file mode 100644 index 000000000000..189fe0f04da8 --- /dev/null +++ b/media/java/android/media/audiopolicy/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 48436 + +elaurent@google.com diff --git a/media/java/android/media/browse/OWNERS b/media/java/android/media/browse/OWNERS new file mode 100644 index 000000000000..916fc36ffbc6 --- /dev/null +++ b/media/java/android/media/browse/OWNERS @@ -0,0 +1,8 @@ +# Bug component: 137631 + +hdmoon@google.com +insun@google.com +jaewan@google.com +jinpark@google.com +klhyun@google.com +gyumin@google.com diff --git a/media/java/android/media/midi/OWNERS b/media/java/android/media/midi/OWNERS new file mode 100644 index 000000000000..6a351d396836 --- /dev/null +++ b/media/java/android/media/midi/OWNERS @@ -0,0 +1 @@ +elaurent@google.com diff --git a/media/java/android/media/session/OWNERS b/media/java/android/media/session/OWNERS new file mode 100644 index 000000000000..916fc36ffbc6 --- /dev/null +++ b/media/java/android/media/session/OWNERS @@ -0,0 +1,8 @@ +# Bug component: 137631 + +hdmoon@google.com +insun@google.com +jaewan@google.com +jinpark@google.com +klhyun@google.com +gyumin@google.com diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java index b1a88ed16bcd..e7d30ebba4b1 100644 --- a/media/java/android/media/session/PlaybackState.java +++ b/media/java/android/media/session/PlaybackState.java @@ -46,7 +46,8 @@ public final class PlaybackState implements Parcelable { ACTION_SKIP_TO_PREVIOUS, ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_SET_RATING, ACTION_SEEK_TO, ACTION_PLAY_PAUSE, ACTION_PLAY_FROM_MEDIA_ID, ACTION_PLAY_FROM_SEARCH, ACTION_SKIP_TO_QUEUE_ITEM, ACTION_PLAY_FROM_URI, ACTION_PREPARE, - ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI}) + ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI, + ACTION_SET_PLAYBACK_SPEED}) @Retention(RetentionPolicy.SOURCE) public @interface Actions {} @@ -176,6 +177,14 @@ public final class PlaybackState implements Parcelable { */ public static final long ACTION_PREPARE_FROM_URI = 1 << 17; + // Note: The value jumps from 1 << 17 to 1 << 22 for matching same value with AndroidX. + /** + * Indicates this session supports the set playback speed command. + * + * @see Builder#setActions(long) + */ + public static final long ACTION_SET_PLAYBACK_SPEED = 1 << 22; + /** * @hide */ @@ -428,6 +437,7 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li> * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li> * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li> + * <li> {@link PlaybackState#ACTION_SET_PLAYBACK_SPEED}</li> * </ul> */ @Actions @@ -823,6 +833,7 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li> * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li> * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li> + * <li> {@link PlaybackState#ACTION_SET_PLAYBACK_SPEED}</li> * </ul> * * @param actions The set of actions allowed. diff --git a/media/java/android/media/soundtrigger/OWNERS b/media/java/android/media/soundtrigger/OWNERS new file mode 100644 index 000000000000..6a351d396836 --- /dev/null +++ b/media/java/android/media/soundtrigger/OWNERS @@ -0,0 +1 @@ +elaurent@google.com diff --git a/media/java/android/media/tv/OWNERS b/media/java/android/media/tv/OWNERS index a891154301ed..8bccc9a9db30 100644 --- a/media/java/android/media/tv/OWNERS +++ b/media/java/android/media/tv/OWNERS @@ -1,9 +1,6 @@ -amyjojo@google.com nchalko@google.com -shubang@google.com quxiangfang@google.com # For android remote service per-file ITvRemoteServiceInput.aidl = file:/media/lib/tvremote/OWNERS per-file ITvRemoteProvider.aidl = file:/media/lib/tvremote/OWNERS - diff --git a/media/java/android/media/tv/tuner/Descrambler.java b/media/java/android/media/tv/tuner/Descrambler.java index 2217eb3a1dc1..700e7beb06c6 100644 --- a/media/java/android/media/tv/tuner/Descrambler.java +++ b/media/java/android/media/tv/tuner/Descrambler.java @@ -110,14 +110,16 @@ public class Descrambler implements AutoCloseable { } /** - * Set a key token to link descrambler to a key slot + * Set a key token to link descrambler to a key slot. Use {@link isValidKeyToken(byte[])} to + * validate the key token format. Invalid key token would cause no-op and return + * {@link Tuner.RESULT_INVALID_ARGUMENT}. * * <p>A descrambler instance can have only one key slot to link, but a key slot can hold a few - * keys for different purposes. + * keys for different purposes. {@link Tuner.VOID_KEYTOKEN} is considered valid. * - * @param keyToken the token to be used to link the key slot. Use {@link Tuner.INVALID_KEYTOKEN} + * @param keyToken the token to be used to link the key slot. Use {@link Tuner.VOID_KEYTOKEN} * to remove the current key from descrambler. If the current keyToken comes from a - * MediaCas session, use {@link Tuner.INVALID_KEYTOKEN} to remove current key before + * MediaCas session, use {@link Tuner.VOID_KEYTOKEN} to remove current key before * closing the MediaCas session. * @return result status of the operation. */ @@ -134,6 +136,22 @@ public class Descrambler implements AutoCloseable { } /** + * Validate the key token format as the parameter of {@link setKeyToken(byte[])}. + * + * <p>The key token is expected to be less than 128 bits. + * + * @param keyToken the token to be validated. + * @return true if the given key token is a valid one. + */ + public static boolean isValidKeyToken(@NonNull byte[] keyToken) { + if (keyToken.length == 0 || keyToken.length > 16) { + Log.d(TAG, "Invalid key token size: " + (keyToken.length * 8) + " bit."); + return false; + } + return true; + } + + /** * Release the descrambler instance. */ @Override @@ -150,18 +168,4 @@ public class Descrambler implements AutoCloseable { } } } - - private boolean isValidKeyToken(byte[] keyToken) { - if (keyToken.length == 0 || keyToken.length > 16) { - Log.d(TAG, "Invalid key token size: " + (keyToken.length * 8) + " bit."); - return false; - } - for (int i = 0; i < keyToken.length; i++) { - if (keyToken[i] < 0) { - Log.d(TAG, "Invalid key token."); - return false; - } - } - return true; - } } diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index da14ee1f3212..d094c2cd3c63 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -167,13 +167,13 @@ public class Tuner implements AutoCloseable { public static final int INVALID_LNB_ID = android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_LNB_ID; /** - * Invalid key token. It is used to remove the current key from descrambler. + * A void key token. It is used to remove the current key from descrambler. * * <p>If the current keyToken comes from a MediaCas session, App is recommended to * to use this constant to remove current key before closing MediaCas session. */ @NonNull - public static final byte[] INVALID_KEYTOKEN = + public static final byte[] VOID_KEYTOKEN = {android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_KEYTOKEN}; /** @hide */ diff --git a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java index 98f80965523f..a2a602a44f3c 100644 --- a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java +++ b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java @@ -341,13 +341,13 @@ public class DvbsFrontendSettings extends FrontendSettings { return mScanType; } /** - * Get if the client could handle the Diseqc Rx Message or not. Default value is false. + * Get if the client can handle the Diseqc Rx Message or not. Default value is false. * - * The setter {@link Builder#setCouldHandleDiseqcRxMessage(boolean)} is only supported with + * The setter {@link Builder#setCanHandleDiseqcRxMessage(boolean)} is only supported with * Tuner HAL 1.1 or higher. Use {@link TunerVersionChecker.getTunerVersion()} to check the * version. */ - public boolean getCouldHandleDiseqcRxMessage() { + public boolean canHandleDiseqcRxMessage() { return mIsDiseqcRxMessage; } @@ -409,7 +409,7 @@ public class DvbsFrontendSettings extends FrontendSettings { } /** - * Set true to indicate the client could handle the Diseqc Messages. Note that it's still + * Set true to indicate the client can handle the Diseqc Messages. Note that it's still * possible that the client won't receive the messages when HAL is not able to setup Rx * channel in the hardware layer. * @@ -417,10 +417,10 @@ public class DvbsFrontendSettings extends FrontendSettings { * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version. */ @NonNull - public Builder setCouldHandleDiseqcRxMessage(boolean couldReceiveDiseqcMessage) { + public Builder setCanHandleDiseqcRxMessage(boolean canHandleDiseqcMessage) { if (TunerVersionChecker.checkHigherOrEqualVersionTo( - TunerVersionChecker.TUNER_VERSION_1_1, "setCouldHandleDiseqcRxMessage")) { - mIsDiseqcRxMessage = couldReceiveDiseqcMessage; + TunerVersionChecker.TUNER_VERSION_1_1, "setCanHandleDiseqcRxMessage")) { + mIsDiseqcRxMessage = canHandleDiseqcMessage; } return this; } diff --git a/media/java/android/mtp/OWNERS b/media/java/android/mtp/OWNERS index 1928ba811e7e..e27d06f4825a 100644 --- a/media/java/android/mtp/OWNERS +++ b/media/java/android/mtp/OWNERS @@ -1,7 +1,7 @@ set noparent marcone@google.com -jsharkey@android.com +jsharkey@google.com jameswei@google.com rmojumder@google.com diff --git a/media/jni/OWNERS b/media/jni/OWNERS index f1b0237d9008..e6e4f86505cf 100644 --- a/media/jni/OWNERS +++ b/media/jni/OWNERS @@ -1,5 +1,5 @@ # extra for MTP related files -per-file android_mtp_*.cpp=marcone@google.com,jsharkey@android.com,jameswei@google.com,rmojumder@google.com +per-file android_mtp_*.cpp=marcone@google.com,jsharkey@google.com,jameswei@google.com,rmojumder@google.com # extra for TV related files per-file android_media_tv_*=nchalko@google.com,quxiangfang@google.com diff --git a/media/mca/effect/java/android/media/effect/OWNERS b/media/mca/effect/java/android/media/effect/OWNERS new file mode 100644 index 000000000000..6a351d396836 --- /dev/null +++ b/media/mca/effect/java/android/media/effect/OWNERS @@ -0,0 +1 @@ +elaurent@google.com diff --git a/media/mca/effect/java/android/media/effect/effects/OWNERS b/media/mca/effect/java/android/media/effect/effects/OWNERS new file mode 100644 index 000000000000..6a351d396836 --- /dev/null +++ b/media/mca/effect/java/android/media/effect/effects/OWNERS @@ -0,0 +1 @@ +elaurent@google.com diff --git a/media/mca/filterfw/java/android/filterfw/OWNERS b/media/mca/filterfw/java/android/filterfw/OWNERS new file mode 100644 index 000000000000..5d351ef97276 --- /dev/null +++ b/media/mca/filterfw/java/android/filterfw/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 50018 + +elaurent@google.com diff --git a/media/mca/filterfw/java/android/filterfw/samples/OWNERS b/media/mca/filterfw/java/android/filterfw/samples/OWNERS new file mode 100644 index 000000000000..5d351ef97276 --- /dev/null +++ b/media/mca/filterfw/java/android/filterfw/samples/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 50018 + +elaurent@google.com diff --git a/media/tests/MtpTests/OWNERS b/media/tests/MtpTests/OWNERS index 1928ba811e7e..e27d06f4825a 100644 --- a/media/tests/MtpTests/OWNERS +++ b/media/tests/MtpTests/OWNERS @@ -1,7 +1,7 @@ set noparent marcone@google.com -jsharkey@android.com +jsharkey@google.com jameswei@google.com rmojumder@google.com diff --git a/mime/OWNERS b/mime/OWNERS new file mode 100644 index 000000000000..6f9dbea36b06 --- /dev/null +++ b/mime/OWNERS @@ -0,0 +1 @@ +include /core/java/android/os/storage/OWNERS diff --git a/mime/java-res/android.mime.types b/mime/java-res/android.mime.types index e5273a927007..92365d1af4c9 100644 --- a/mime/java-res/android.mime.types +++ b/mime/java-res/android.mime.types @@ -63,6 +63,7 @@ ?application/x-android-drm-fl fl ?application/x-flac flac ?application/x-font pcf +?application/x-mobipocket-ebook prc mobi ?application/x-mpegurl m3u m3u8 ?application/x-pem-file pem ?application/x-pkcs12 p12 pfx diff --git a/native/android/aidl/com/android/internal/compat/OWNERS b/native/android/aidl/com/android/internal/compat/OWNERS new file mode 100644 index 000000000000..f8c3520e9fa8 --- /dev/null +++ b/native/android/aidl/com/android/internal/compat/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/compat/OWNERS diff --git a/native/graphics/OWNERS b/native/graphics/OWNERS new file mode 100644 index 000000000000..a6d1bc37d27d --- /dev/null +++ b/native/graphics/OWNERS @@ -0,0 +1 @@ +include /core/java/android/graphics/OWNERS diff --git a/opengl/java/android/opengl/OWNERS b/opengl/java/android/opengl/OWNERS new file mode 100644 index 000000000000..9c6c610de52a --- /dev/null +++ b/opengl/java/android/opengl/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 25421 + +sumir@google.com +prahladk@google.com diff --git a/packages/AppPredictionLib/OWNERS b/packages/AppPredictionLib/OWNERS new file mode 100644 index 000000000000..3a5d23d6928f --- /dev/null +++ b/packages/AppPredictionLib/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/appprediction/OWNERS diff --git a/packages/Backup/OWNERS b/packages/Backup/OWNERS new file mode 100644 index 000000000000..d99779e3d9da --- /dev/null +++ b/packages/Backup/OWNERS @@ -0,0 +1 @@ +include /services/backup/OWNERS diff --git a/packages/BackupEncryption/OWNERS b/packages/BackupEncryption/OWNERS new file mode 100644 index 000000000000..d99779e3d9da --- /dev/null +++ b/packages/BackupEncryption/OWNERS @@ -0,0 +1 @@ +include /services/backup/OWNERS diff --git a/packages/BackupRestoreConfirmation/OWNERS b/packages/BackupRestoreConfirmation/OWNERS new file mode 100644 index 000000000000..d99779e3d9da --- /dev/null +++ b/packages/BackupRestoreConfirmation/OWNERS @@ -0,0 +1 @@ +include /services/backup/OWNERS diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml index 5247ac9b1e68..91bad7b4aa91 100644 --- a/packages/CompanionDeviceManager/AndroidManifest.xml +++ b/packages/CompanionDeviceManager/AndroidManifest.xml @@ -31,6 +31,7 @@ <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> <uses-permission android:name="android.permission.RADIO_SCAN_WITHOUT_LOCATION"/> <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/> + <uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"/> <application android:allowClearUserData="true" diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java index 2fe351edb080..fd71670ee404 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java @@ -321,7 +321,8 @@ public class DeviceDiscoveryService extends Service { } void onDeviceSelected(String callingPackage, String deviceAddress) { - mServiceCallback.complete(new Association(getUserId(), deviceAddress, callingPackage)); + mServiceCallback.complete(new Association( + getUserId(), deviceAddress, callingPackage, mRequest.getDeviceProfile(), false)); } void onCancel() { diff --git a/packages/CtsShim/build/Android.bp b/packages/CtsShim/build/Android.bp index 43e386852713..14a3376380df 100644 --- a/packages/CtsShim/build/Android.bp +++ b/packages/CtsShim/build/Android.bp @@ -34,6 +34,8 @@ android_app { compile_multilib: "both", jni_libs: ["libshim_jni"], + + uses_libs: ["android.test.runner"], } genrule { @@ -108,6 +110,7 @@ android_app { compile_multilib: "both", jni_libs: ["libshim_jni"], + uses_libs: ["android.test.runner"], } //########################################################## diff --git a/packages/EasterEgg/OWNERS b/packages/EasterEgg/OWNERS new file mode 100644 index 000000000000..2e96c97c8bb3 --- /dev/null +++ b/packages/EasterEgg/OWNERS @@ -0,0 +1 @@ +include /packages/SystemUI/OWNERS diff --git a/packages/ExternalStorageProvider/OWNERS b/packages/ExternalStorageProvider/OWNERS new file mode 100644 index 000000000000..6f9dbea36b06 --- /dev/null +++ b/packages/ExternalStorageProvider/OWNERS @@ -0,0 +1 @@ +include /core/java/android/os/storage/OWNERS diff --git a/packages/FusedLocation/OWNERS b/packages/FusedLocation/OWNERS new file mode 100644 index 000000000000..5ac6028411f0 --- /dev/null +++ b/packages/FusedLocation/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/location/OWNERS diff --git a/packages/MtpDocumentsProvider/OWNERS b/packages/MtpDocumentsProvider/OWNERS new file mode 100644 index 000000000000..6f9dbea36b06 --- /dev/null +++ b/packages/MtpDocumentsProvider/OWNERS @@ -0,0 +1 @@ +include /core/java/android/os/storage/OWNERS diff --git a/packages/OsuLogin/res/values-my/strings.xml b/packages/OsuLogin/res/values-my/strings.xml deleted file mode 100644 index 1bd992e8485b..000000000000 --- a/packages/OsuLogin/res/values-my/strings.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string> - <string name="action_bar_label" msgid="550995560341508693">"အွန်လိုင်း အကောင့်ဖွင့်ရန်"</string> - <string name="sign_up_failed" msgid="837216244603867568">"အကောင့်ဖွင့်၍ မရပါ"</string> -</resources> diff --git a/packages/PrintRecommendationService/OWNERS b/packages/PrintRecommendationService/OWNERS new file mode 100644 index 000000000000..2c7b881faf0f --- /dev/null +++ b/packages/PrintRecommendationService/OWNERS @@ -0,0 +1 @@ +include /core/java/android/print/OWNERS diff --git a/packages/PrintSpooler/OWNERS b/packages/PrintSpooler/OWNERS new file mode 100644 index 000000000000..2c7b881faf0f --- /dev/null +++ b/packages/PrintSpooler/OWNERS @@ -0,0 +1 @@ +include /core/java/android/print/OWNERS diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp index e6492aadd765..23cb36fc2a90 100644 --- a/packages/SettingsLib/Android.bp +++ b/packages/SettingsLib/Android.bp @@ -54,6 +54,7 @@ java_defaults { "SettingsLibEmergencyNumber", "SettingsLibTopIntroPreference", "SettingsLibBannerMessagePreference", + "SettingsLibFooterPreference", ], } diff --git a/packages/SettingsLib/FooterPreference/Android.bp b/packages/SettingsLib/FooterPreference/Android.bp new file mode 100644 index 000000000000..30d9bd23cd0c --- /dev/null +++ b/packages/SettingsLib/FooterPreference/Android.bp @@ -0,0 +1,13 @@ +android_library { + name: "SettingsLibFooterPreference", + + srcs: ["src/**/*.java"], + resource_dirs: ["res"], + + static_libs: [ + "androidx.annotation_annotation", + "androidx.preference_preference", + ], + sdk_version: "system_current", + min_sdk_version: "21", +} diff --git a/packages/SettingsLib/FooterPreference/AndroidManifest.xml b/packages/SettingsLib/FooterPreference/AndroidManifest.xml new file mode 100644 index 000000000000..96d9e518663f --- /dev/null +++ b/packages/SettingsLib/FooterPreference/AndroidManifest.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.settingslib.widget"> + + <uses-sdk android:minSdkVersion="21" /> + +</manifest> diff --git a/packages/SettingsLib/res/drawable/ic_info_outline_24.xml b/packages/SettingsLib/FooterPreference/res/drawable/ic_info_outline_24.xml index 317e43b95cdd..d9afeb0a6361 100644 --- a/packages/SettingsLib/res/drawable/ic_info_outline_24.xml +++ b/packages/SettingsLib/FooterPreference/res/drawable/ic_info_outline_24.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright (C) 2019 The Android Open Source Project + Copyright (C) 2020 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/packages/SystemUI/res/color/qs_background_dark.xml b/packages/SettingsLib/FooterPreference/res/values/attrs.xml index c47959a04fff..deba3af2b910 100644 --- a/packages/SystemUI/res/color/qs_background_dark.xml +++ b/packages/SettingsLib/FooterPreference/res/values/attrs.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2017 The Android Open Source Project +<!-- Copyright (C) 2020 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,7 +14,6 @@ limitations under the License. --> -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:alpha="1" - android:color="?android:attr/colorBackground"/> -</selector> +<resources> + <attr name="footerPreferenceStyle" format="reference" /> +</resources>
\ No newline at end of file diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java b/packages/SettingsLib/FooterPreference/src/com/android/settingslib/widget/FooterPreference.java index 15576182c53a..15301f616f8b 100644 --- a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java +++ b/packages/SettingsLib/FooterPreference/src/com/android/settingslib/widget/FooterPreference.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package com.android.settingslib.widget; -import android.annotation.StringRes; import android.content.Context; import android.text.TextUtils; import android.text.method.LinkMovementMethod; @@ -24,20 +23,19 @@ import android.util.AttributeSet; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.annotation.StringRes; import androidx.core.content.res.TypedArrayUtils; import androidx.preference.Preference; import androidx.preference.PreferenceViewHolder; -import com.android.settingslib.R; - /** * A custom preference acting as "footer" of a page. It has a field for icon and text. It is added * to screen as the last preference. */ public class FooterPreference extends Preference { - static final int ORDER_FOOTER = Integer.MAX_VALUE - 1; public static final String KEY_FOOTER = "footer_preference"; + static final int ORDER_FOOTER = Integer.MAX_VALUE - 1; public FooterPreference(Context context, AttributeSet attrs) { super(context, attrs, TypedArrayUtils.getAttr( diff --git a/packages/SettingsLib/HelpUtils/res/values-ar/strings.xml b/packages/SettingsLib/HelpUtils/res/values-ar/strings.xml index 7ab3abcf7540..5b12fc586ef9 100644 --- a/packages/SettingsLib/HelpUtils/res/values-ar/strings.xml +++ b/packages/SettingsLib/HelpUtils/res/values-ar/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="help_feedback_label" msgid="7106780063063027882">"المساعدة والتعليقات"</string> + <string name="help_feedback_label" msgid="7106780063063027882">"المساعدة والملاحظات والآراء"</string> </resources> diff --git a/packages/SettingsLib/OWNERS b/packages/SettingsLib/OWNERS index 8eafbdfdf6bc..30c10d3ef3b8 100644 --- a/packages/SettingsLib/OWNERS +++ b/packages/SettingsLib/OWNERS @@ -1,5 +1,5 @@ # People who can approve changes for submission -dsandler@android.com +dsandler@google.com edgarwang@google.com emilychuang@google.com evanlaird@google.com diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index 41af185da0b7..438e8b8c5bf2 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktief. Tik om te wissel."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Programbystandstatus:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Mediakodewisselinginstellings"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Deaktiveer kodewisseling"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Ignoreer kodewisselingverstekke"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Aktiveer kodewisseling"</string> + <string name="transcode_default" msgid="3784803084573509491">"Aanvaar dat programme moderne formate steun"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktiveer kodewisseling vir programme"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Lopende dienste"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Sien en beheer dienste wat tans aktief is"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> oor tot battery gelaai is"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot battery gelaai is"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery word tydelik beperk"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimeer tans vir batterygesondheid"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Laai"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laai tans vinnig"</string> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index 8e4e402c2e16..fd5777d5fe70 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"ገቢር። ለመቀያየር ነካ ያድርጉ።"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"የመተግበሪያ ዝግጁ የመሆን ሁኔታ፦<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"የሚዲያ ትራንስኮዲንግ ቅንብሮች"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ትራንስኮንግን አሰናክል"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"የትራንስኮዲንግ ነባሪዎችን ሻር"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"ትራንስኮዲንግን ያንቁ"</string> + <string name="transcode_default" msgid="3784803084573509491">"መተግበሪያዎች ዘመናዊ ቅርጸቶችን እንደሚደግፉ አድርገው ይቁጠሩ"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"ለመተግበሪያዎች ትራንስኮዲንግን ያንቁ"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"አሂድ አገልግሎቶች"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"በአሁኑጊዜ እየሄዱ ያሉ አገልግሎቶችን ተቆጣጠር እና እይ"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ኃይል እስከሚሞላ ድረስ ይቀራል"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ኃይል እስከሚሞላ ድረስ"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ባትሪ ለጊዜው ተገድቧል"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ለባትሪ ጤና ማመቻቸት"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ያልታወቀ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ኃይል በመሙላት ላይ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ኃይል በፍጥነት በመሙላት ላይ"</string> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index 691ec046da02..b81031ee5835 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"نشط، انقر للتبديل."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"حالة تطبيق وضع الاستعداد:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"إعدادات تحويل ترميز الوسائط"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"إيقاف تحويل الترميز"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"إلغاء الإعدادات التلقائية لتحويل الترميز"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"تفعيل تحويل الترميز"</string> + <string name="transcode_default" msgid="3784803084573509491">"افتراض أن التطبيق يتوافق مع التنسيقات الحديثة"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"تفعيل تحويل الترميز للتطبيقات"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"الخدمات قيد التشغيل"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"عرض الخدمات قيد التشغيل في الوقت الحالي والتحكم فيها"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> إلى أن يتم شحن الجهاز بالكامل"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> إلى أن يتم شحن الجهاز بالكامل"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - تأثير محدود على البطارية مؤقتًا"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - التحسين لسلامة البطارية"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"غير معروف"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"جارٍ الشحن"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"جارٍ الشحن سريعًا"</string> @@ -518,7 +520,7 @@ <string name="media_transfer_this_device_name" msgid="2716555073132169240">"مكبر صوت الهاتف"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"حدثت مشكلة أثناء الاتصال. يُرجى إيقاف الجهاز ثم إعادة تشغيله."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"جهاز سماعي سلكي"</string> - <string name="help_label" msgid="3528360748637781274">"المساعدة والتعليقات"</string> + <string name="help_label" msgid="3528360748637781274">"المساعدة والملاحظات والآراء"</string> <string name="storage_category" msgid="2287342585424631813">"مساحة التخزين"</string> <string name="shared_data_title" msgid="1017034836800864953">"البيانات المشتركة"</string> <string name="shared_data_summary" msgid="5516326713822885652">"عرض البيانات المشتركة وتعديلها"</string> diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml index 61214e09ba26..e4823299c296 100644 --- a/packages/SettingsLib/res/values-as/strings.xml +++ b/packages/SettingsLib/res/values-as/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"সক্ৰিয়। ট\'গল কৰিবলৈ টিপক।"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"এপ্ ষ্টেণ্ডবাই অৱস্থাত আছে:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"মিডিয়া ট্ৰান্সক\'ডিঙৰ ছেটিং"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ট্ৰান্সক\'ডিং অক্ষম কৰক"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"ট্ৰেন্সক’ডিং ডিফ’ল্ট অ’ভাৰৰাইড কৰক"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"ট্ৰেন্সক’ডিং সক্ষম কৰক"</string> + <string name="transcode_default" msgid="3784803084573509491">"এপে আধুনিক ফৰ্মেট সমৰ্থন কৰে বুলি ধৰি লওক"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"এপৰ বাবে ট্ৰান্সক\'ডিং সক্ষম কৰক"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"চলিত সেৱা"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"বৰ্তমান চলি থকা সেৱাসমূহ চাওক আৰু নিয়ন্ত্ৰণ কৰক"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"চাৰ্জ হ’বলৈ <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> চাৰ্জ হ\'বলৈ"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - বেটাৰী সাময়িকভাৱে সীমিত কৰা হৈছে"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - বেটাৰীৰ অৱস্থা অপ্টিমাইজ কৰি থকা হৈছে"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"অজ্ঞাত"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"চাৰ্জ কৰি থকা হৈছে"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্ৰুততাৰে চাৰ্জ হৈছে"</string> diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml index db61527a54d8..637785d06d2e 100644 --- a/packages/SettingsLib/res/values-az/strings.xml +++ b/packages/SettingsLib/res/values-az/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivdir. Keçid etmək üçün basın."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Tətbiqin gözləmə rejimi:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Media yenidən kodlaşdırma ayarları"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Yenidən kodlaşdırmanı deaktiv edin"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Yenidən kodlaşdırma defoltlarını əvəzləyin"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Yenidən kodlaşdırmanı aktiv edin"</string> + <string name="transcode_default" msgid="3784803084573509491">"Tətbiqlərin müasir formatları dəstəklədiyini qəbul edin"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Tətbiqlər üçün yenidən kodlaşdırmanı aktiv edin"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"İşləyən xidmətlər"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Hazırda prosesdə olan xidmətləri görüntüləyin və onlara nəzarət edin"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Enerjinin dolmasına <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - Enerjinin dolmasına <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batareya müvəqqəti məhdudlaşdırılıb"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Enerjiyə qənaət üçün optimallaşdırma"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Naməlum"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Enerji doldurma"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Sürətlə doldurulur"</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index 70fb3636b492..219d5a072c45 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivna. Dodirnite da biste je deaktivirali."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stanje pripravnosti aplikacije: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Podešavanja transkodiranja medija"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Onemogući transkodiranje"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Zameni podrazumevana podešavanja transkodiranja"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Omogući transkodiranje"</string> + <string name="transcode_default" msgid="3784803084573509491">"Podrazumevaj da aplikacije podržavaju moderne formate"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Omogućite transkodiranje za aplikacije"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Pokrenute usluge"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Prikaz i kontrola trenutno pokrenutih usluga"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napuniće se za <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napuniće se za <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – baterija je trenutno ograničena"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimizuje se radi stanja baterije"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Puni se"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo se puni"</string> diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml index 8a0db8261a71..4772e032268f 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Актыўная. Краніце, каб пераключыць."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Стан праграмы ў рэжыме чакання: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Налады перакадзіравання мультымедыя"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Выключыць перакадзіраванне"</string> + <!-- no translation found for transcode_user_control (6176368544817731314) --> + <skip /> + <!-- no translation found for transcode_enable_all (2411165920039166710) --> + <skip /> + <!-- no translation found for transcode_default (3784803084573509491) --> + <skip /> <string name="transcode_skip_apps" msgid="8249721984597390142">"Уключыць перакадзіраванне для праграм"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Запушчаныя службы"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Прагляд запушчаных службаў i кіраванне iмi"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Засталося <xliff:g id="TIME">%1$s</xliff:g> да поўнай зарадкі"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарад акумулятара часова абмежаваны"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Аптымізацыя стану акумулятара"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Невядома"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарадка"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хуткая зарадка"</string> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index 27dcf105fd2e..75d1eeb1093f 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Активно. Докоснете, за да превключите."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Състояние на готовност на приложението: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Настройки за прекодирането на мултимедия"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Деактивиране на прекодирането"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Отмяна на стандартните настройки за прекодирането"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Активиране на прекодирането"</string> + <string name="transcode_default" msgid="3784803084573509491">"Предполагане, че приложенията поддържат съвременни формати"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Активиране на прекодирането за приложения"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Изпълнявани услуги"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Преглед и контрол върху изпълняващите се понастоящем услуги"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Оставащо време до пълно зареждане: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Батерията е временно ограничена"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Оптимизиране за състоян. на батерията"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарежда се"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Зарежда се бързо"</string> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index 29862e6efd31..325f2bdc5807 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"সক্রিয় রয়েছে৷ টগল করতে আলতো চাপুন৷"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"অ্যাপ স্ট্যান্ডবাই-এর অবস্থা:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"মিডিয়া ট্রান্সকোডিং সেটিংস"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ট্রান্সকোডিং বন্ধ করুন"</string> + <!-- no translation found for transcode_user_control (6176368544817731314) --> + <skip /> + <!-- no translation found for transcode_enable_all (2411165920039166710) --> + <skip /> + <!-- no translation found for transcode_default (3784803084573509491) --> + <skip /> <string name="transcode_skip_apps" msgid="8249721984597390142">"অ্যাপের জন্য ট্রান্সকোডিং চালু করুন"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"এখন চলছে যে পরিষেবাগুলি"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"বর্তমান চলমান পরিষেবাগুলি দেখুন এবং নিয়ন্ত্রণ করুন"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"সম্পূর্ণ চার্জ হতে <xliff:g id="TIME">%1$s</xliff:g> বাকি আছে"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-এ সম্পূর্ণ চার্জ হয়ে যাবে"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ব্যাটারি কিছুক্ষণের জন্য সীমিত করা হয়েছে"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ব্যাটারির চার্জ অপটিমাইজ করা হচ্ছে"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"অজানা"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"চার্জ হচ্ছে"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্রুত চার্জ হচ্ছে"</string> diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml index 4704ec8db79a..ab4ac1460d6f 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Greška u konfiguraciji IP-a"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Niste povezani zbog slabog kvaliteta mreže"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Greška pri povezivanju na WiFi"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problem pri autentifikaciji."</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problem pri autentifikaciji"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"Nije se moguće povezati"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Nije se moguće povezati na aplikaciju \'<xliff:g id="AP_NAME">%1$s</xliff:g>\'"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Provjerite lozinku i pokušajte ponovo"</string> @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivno. Dodirnite za promjenu opcije."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stanje mirovanja aplikacije:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Postavke transkodiranja medija"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Onemogućite transkodiranje"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Zaobiđi zadane postavke transkodiranja"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Omogući transkodiranje"</string> + <string name="transcode_default" msgid="3784803084573509491">"Pretpostavi da aplikacije podržavaju moderne formate"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Omogućite transkodiranje za aplikacije"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Pokrenute usluge"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Prikaz i kontrola trenutno pokrenutih usluga"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napunit će se za <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napunit će se za <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Baterija je privremeno ograničena"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimiziranje radi očuvanja baterije"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index 5d04963d9b4a..9bb919f39091 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aplicació activa. Toca per desactivar-la."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Estat de les aplicacions inactives: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Configuració de la transcodificació de contingut multimèdia"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Desactiva la transcodificació"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Substitueix els valors predeterminats de la transcodificació"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Activa la transcodificació"</string> + <string name="transcode_default" msgid="3784803084573509491">"Assumeix que les aplicacions són compatibles amb formats moderns"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Activa la transcodificació per a les aplicacions"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Serveis en execució"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualitza i controla els serveis en execució"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> per completar la càrrega"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: bateria limitada temporalment"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: optimitzant per a l\'estat de la bateria"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconegut"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"S\'està carregant"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregant ràpidament"</string> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index a99a4dabbc60..5f2e00534461 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivní. Klepnutím možnost přepnete."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stav pohotovostního režimu aplikace: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Nastavení překódování médií"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Zakázat překódování"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Přepsat výchozí nastavení překódování"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Povolit překódování"</string> + <string name="transcode_default" msgid="3784803084573509491">"Předpokládat, že aplikace podporují moderní formáty"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Povolit překódování pro aplikace"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Spuštěné služby"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Umožňuje zobrazit a ovládat aktuálně spuštěné služby"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Do nabití zbývá: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do nabití"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Baterie dočasně omezena"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimalizace pro výdrž baterie"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznámé"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíjí se"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rychlé nabíjení"</string> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index c90155eb2b68..f4f46507a9f3 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Tryk for at skifte."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Standbystatus for appen:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Indstillinger for omkodning af medier"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Deaktiver omkodning"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Tilsidesæt standardindstillingerne for omkodning"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Aktivér omkodning"</string> + <string name="transcode_default" msgid="3784803084573509491">"Gå ud fra, at apps understøtter moderne formater"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktivér omkodning for apps"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Kørende tjenester"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Vis og administrer kørende tjenester"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Opladet om <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – opladet om <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Batteriet er midlertidigt begrænset"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimerer batteritilstanden"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Ukendt"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Oplader"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Oplader hurtigt"</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index b5b9fc480607..1d6894b097f7 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Zum Wechseln tippen."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Standby-Status der App:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Einstellungen für Medientranscodierung"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Transcodierung deaktivieren"</string> + <!-- no translation found for transcode_user_control (6176368544817731314) --> + <skip /> + <!-- no translation found for transcode_enable_all (2411165920039166710) --> + <skip /> + <!-- no translation found for transcode_default (3784803084573509491) --> + <skip /> <string name="transcode_skip_apps" msgid="8249721984597390142">"Transcodierung für Apps aktivieren"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Aktive Dienste"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Momentan ausgeführte Dienste anzeigen und steuern"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Noch <xliff:g id="TIME">%1$s</xliff:g> bis zur Aufladung"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> bis zur Aufladung"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akku vorübergehend eingeschränkt"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimierung des Akkuzustands"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unbekannt"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Wird aufgeladen"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Schnelles Aufladen"</string> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index 203ec40c5a42..3affbce49f09 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Ενεργό. Πατήστε για εναλλαγή."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Κατάσταση αναμονής εφαρμογής:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Ρυθμίσεις διακωδικοποίησης μέσων"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Απενεργοποίηση διακωδικοποίησης"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Παράκαμψη προεπιλογών διακωδικοποίησης"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Ενεργοποίηση διακωδικοποίησης"</string> + <string name="transcode_default" msgid="3784803084573509491">"Να θεωρείται ότι οι εφαρμογές χρησιμοποιούν σύγχρονες μορφές"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Ενεργοποίηση διακωδικοποίησης για εφαρμογές"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Υπηρεσίες που εκτελούνται"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Προβολή και έλεγχος των εφαρμογών που εκτελούνται αυτή τη στιγμή"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Απομένουν <xliff:g id="TIME">%1$s</xliff:g> για ολοκλήρωση της φόρτισης"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για την ολοκλήρωση της φόρτισης"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Η μπαταρία περιορίστηκε προσωρινά."</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Βελτιστοποίηση κατάστασης μπαταρίας"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Άγνωστο"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Φόρτιση"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ταχεία φόρτιση"</string> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index f8019d21c65b..9d5debba80c5 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string> + <string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery limited temporarily"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimising for battery health"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string> diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml index 7135de5676b2..b0190a2e1112 100644 --- a/packages/SettingsLib/res/values-en-rCA/strings.xml +++ b/packages/SettingsLib/res/values-en-rCA/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string> + <string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery limited temporarily"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimising for battery health"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index f8019d21c65b..9d5debba80c5 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string> + <string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery limited temporarily"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimising for battery health"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index f8019d21c65b..9d5debba80c5 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string> + <string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery limited temporarily"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimising for battery health"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string> diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml index 54290d269f44..9296a5968ec1 100644 --- a/packages/SettingsLib/res/values-en-rXC/strings.xml +++ b/packages/SettingsLib/res/values-en-rXC/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string> + <string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Battery limited temporarily"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Optimizing for battery health"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index 08ff55099c9c..41466be75fb7 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Activa. Presiona para activar o desactivar."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado de la app en espera: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Configuración de transcodificación de contenido multimedia"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Inhabilitar transcodificación"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Anular los valores predeterminados de transcodificación"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Habilitar la transcodificación"</string> + <string name="transcode_default" msgid="3784803084573509491">"Suponer que las apps admiten formatos modernos"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Habilitar transcodificación en apps"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"En ejecución"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ver y controlar servicios actuales en ejecución"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> para completar la carga"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batería limitada temporalmente"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: Optimizando el estado de la batería"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rápido"</string> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index 6f6a1a1c9b17..8a0a123081e3 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Activa. Toca para alternar."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado de la aplicación en espera: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Configuración de la transcodificación multimedia"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Inhabilitar transcodificación"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Anular valores predeterminados de transcodificación"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Habilitar transcodificación"</string> + <string name="transcode_default" msgid="3784803084573509491">"Considerar que las aplicaciones admiten formatos modernos"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Habilitar transcodificación en las aplicaciones"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Servicios en ejecución"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ver y controlar los servicios en ejecución"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> hasta cargarse completamente"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> hasta cargarse completamente)"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: batería limitada temporalmente"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: preservando estado de la batería"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rápidamente"</string> diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml index 9d6326e45706..4b82c08a46e7 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiivne. Puudutage vahetamiseks."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Rakenduse ootelolek:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Meedia transkodeerimise seaded"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Keela transkodeerimine"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Alista transkodeerimise vaikeseaded"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Luba transkodeerimine"</string> + <string name="transcode_default" msgid="3784803084573509491">"Oleta, et rakendused toetavad kaasaegseid vorminguid"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Luba rakenduste puhul transkodeerimine"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Käitatud teenused"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Praegu käitatud teenuste vaatamine ja juhtimine"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Täislaadimiseni on jäänud <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täislaadimiseni"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – akutase on ajutiselt piiratud"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – optimeerimine aku seisukorra põhjal"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Tundmatu"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Laadimine"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Kiirlaadimine"</string> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index 01afa1706e3e..37c1fd8db552 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktibo. Aldatzeko, sakatu hau."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Egonean moduko aplikazioaren egoera: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Multimedia-edukia transkodetzeko ezarpenak"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Desgaitu transkodetzeko aukera"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Ez erabili transkodetzearen balio lehenetsiak"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Gaitu transkodetzea"</string> + <string name="transcode_default" msgid="3784803084573509491">"Arduratu aplikazioek formatu modernoak onartzeaz"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Gaitu aplikazioak transkodetzeko aukera"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Abian diren zerbitzuak"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ikusi eta kontrolatu une honetan abian diren zerbitzuak"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> guztiz kargatu arte"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: bateria mugatuta egongo da aldi batez"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Optimizatzen bateria egoera onean mantentzeko"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Ezezaguna"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Kargatzen"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Bizkor kargatzen"</string> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index dd7ab9672e96..7d20aaf0f5f7 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -34,7 +34,7 @@ <string name="wifi_check_password_try_again" msgid="8817789642851605628">"گذرواژه را بررسی و دوباره امتحان کنید"</string> <string name="wifi_not_in_range" msgid="1541760821805777772">"در محدوده نیست"</string> <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"اتصال بهصورت خودکار انجام نمیشود"</string> - <string name="wifi_no_internet" msgid="1774198889176926299">"بدون دسترسی به اینترنت"</string> + <string name="wifi_no_internet" msgid="1774198889176926299">"دسترسی به اینترنت ندارد"</string> <string name="saved_network" msgid="7143698034077223645">"ذخیرهشده توسط <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="connected_via_network_scorer" msgid="7665725527352893558">"اتصال خودکار ازطریق %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"اتصال خودکار ازطریق ارائهدهنده رتبهبندی شبکه"</string> @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"فعال. برای تغییر حالت ضربه بزنید."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"وضعیت حالت آماده بهکار برنامه:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"تنظیمات تراتبدیل رسانه"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"غیرفعال کردن تراتبدیل"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"ملغی کردن پیشفرضهای تراتبدیل"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"فعال کردن تراتبدیل"</string> + <string name="transcode_default" msgid="3784803084573509491">"فرض شود برنامهها از قالبهای مدرن پشتیبانی میکنند"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"فعال کردن تراتبدیل برای برنامهها"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"سرویسهای در حال اجرا"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"مشاهده و کنترل سرویسهای در حال اجرای فعلی"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> مانده تا شارژ کامل"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - باتری موقتاً محدود شده است"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - بهینهسازی برای سلامت باتری"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ناشناس"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"در حال شارژ شدن"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"درحال شارژ شدن سریع"</string> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index b86b02d8c25f..a43c5d706e3b 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiivinen. Vaihda koskettamalla."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Sovelluksen valmiusluokka: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Median transkoodausasetukset"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Poista transkoodaus käytöstä"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Ohita transkoodauksen oletukset"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Salli transkoodaus"</string> + <string name="transcode_default" msgid="3784803084573509491">"Oleta, että sovellukset tukevat nykyaikaisia formaatteja"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Ota sovellusten transkoodaus käyttöön"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Käynnissä olevat palvelut"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Tarkastele ja hallitse käynnissä olevia palveluita."</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jäljellä täyteen lataukseen"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täyteen lataukseen"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akun käyttöä rajoitettu tilapäisesti"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akun kunnon optimointi"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Tuntematon"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Ladataan"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Nopea lataus"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index 0bca1dba1aa4..0cb7b1746101 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Application active. Touchez ici pour la désactiver."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"État de l\'application en veille :<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Paramètres de transcodage des éléments multimédias"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Désactiver le transcodage"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Remplacer les valeurs par défaut de transcodage"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Activer le transcodage"</string> + <string name="transcode_default" msgid="3784803084573509491">"Présumer que les applications prennent en charge les formats modernes"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Activer le transcodage pour les applications"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Services en cours d\'exécution"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Afficher et contrôler les services en cours d\'exécution"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à la charge complète"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> : <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Pile limitée temporairement"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimisation pour la santé de la pile"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charge en cours…"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Recharge rapide"</string> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index ebde43ba52a2..e928a48fca26 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Échec de configuration de l\'adresse IP"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Non connecté en raison de la faible qualité du réseau"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Échec de la connexion Wi-Fi"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problème d\'authentification."</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problème d\'authentification"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"Connexion impossible"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Impossible de se connecter au réseau \"<xliff:g id="AP_NAME">%1$s</xliff:g>\""</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Vérifiez le mot de passe et réessayez"</string> @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Application active. Appuyez ici pour la désactiver."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"État de mise en veille de l\'application : <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Paramètres de transcodage des contenus multimédias"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Désactiver le transcodage"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Ignorer les paramètres de transcodage par défaut"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Activer le transcodage"</string> + <string name="transcode_default" msgid="3784803084573509491">"Supposer que les applications sont compatibles avec les formats modernes"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Activer le transcodage pour les applications"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Services en cours d\'exécution"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Afficher et contrôler les services en cours d\'exécution"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à ce que la batterie soit chargée"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batterie limitée temporairement"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Optimisation pour préserver batterie"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Batterie en charge"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charge rapide"</string> diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml index b040817b2801..c43925375a2b 100644 --- a/packages/SettingsLib/res/values-gl/strings.xml +++ b/packages/SettingsLib/res/values-gl/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aplicación activa. Toca para alternar a configuración."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado en espera da aplicación: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Configuración de transcodificación de contido multimedia"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Desactivar transcodificación"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Anular valores predeterminados de transcodificación"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Activar transcodificación"</string> + <string name="transcode_default" msgid="3784803084573509491">"Considerar que as aplicacións admiten formatos modernos"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Activar transcodificación para as aplicacións"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Servizos en uso"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Comproba e controla os servizos actualmente en uso"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> para completar a carga"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar a carga"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> (batería limitada temporalmente)"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: optimizando para manter a batería en bo estado"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Descoñecido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rapidamente"</string> diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml index c1bd7cac30a6..7dfdceeaf867 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"સક્રિય. ટોગલ કરવા માટે ટૅપ કરો."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ઍપ સ્ટૅન્ડબાયની સ્થિતિ:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"મીડિયાનું ફૉર્મેટ બદલવાની પ્રક્રિયાના સેટિંગ"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ફૉર્મેટ બદલવાની પ્રક્રિયા બંધ કરો"</string> + <!-- no translation found for transcode_user_control (6176368544817731314) --> + <skip /> + <!-- no translation found for transcode_enable_all (2411165920039166710) --> + <skip /> + <!-- no translation found for transcode_default (3784803084573509491) --> + <skip /> <string name="transcode_skip_apps" msgid="8249721984597390142">"ઍપ માટે ફૉર્મેટ બદલવાની પ્રક્રિયા ચાલુ કરો"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"ચાલુ સેવાઓ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"હાલમાં ચાલતી સેવાઓ જુઓ અને નિયંત્રિત કરો"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ચાર્જ થવામાં <xliff:g id="TIME">%1$s</xliff:g> બાકી છે"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ચાર્જ થવા માટે <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - બૅટરીનો વપરાશ હંગામી રૂપે મર્યાદિત છે"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> • બૅટરીની ક્ષમતા વધારવા ઑપ્ટિમાઇઝ કરી રહ્યાં છીએ"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"અજાણ્યું"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ચાર્જ થઈ રહ્યું છે"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ઝડપથી ચાર્જ થાય છે"</string> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index d9153a1ab542..26d1a756318d 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP कॉन्फ़िगरेशन की विफलता"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"खराब नेटवर्क होने के कारण कनेक्ट नहीं हुआ"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"वाईफ़ाई कनेक्शन विफलता"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"प्रमाणीकरण समस्या"</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"पुष्टि नहीं हो सकी"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"कनेक्ट नहीं हो पा रहा है"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\' से कनेक्ट नहीं हो पा रहा है"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"पासवर्ड जाँचें और दोबारा कोशिश करें"</string> @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"सक्रिय. टॉगल करने के लिए टैप करें."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ऐप्लिकेशन स्टैंडबाय की स्थिति:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"मीडिया ट्रांसकोडिंग सेटिंग"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ट्रांसकोडिंग को बंद करें"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"ट्रांसकोडिंग की डिफ़ॉल्ट सेटिंग बदलें"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"ट्रांसकोडिंग चालू करें"</string> + <string name="transcode_default" msgid="3784803084573509491">"मानकर चलें कि ऐप्लिकेशन, मॉडर्न फ़ॉर्मैट के साथ काम करेंगे"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"ऐप्लिकेशन के लिए ट्रांसकोडिंग चालू करें"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"चल रही सेवाएं"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"इस समय चल रही सेवाओं को देखें और नियंत्रित करें"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"चार्ज पूरा होने में <xliff:g id="TIME">%1$s</xliff:g> बचा है"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> में पूरा चार्ज हो जाएगा"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - कुछ समय के लिए, बैटरी का सीमित इस्तेमाल होगा"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - बैटरी की परफ़ॉर्मेंस बेहतर करने के लिए, ऑप्टिमाइज़ किया जा रहा है"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हो रही है"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"तेज़ चार्ज हो रही है"</string> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index b51e096ca6b7..eccfd7ad56ba 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivno. Dodirnite da biste to promijenili."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stanje aplikacije u mirovanju: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Postavke konvertiranja medija"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Onemogućivanje konvertiranja"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Nadjačaj zadane postavke konvertiranja"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Omogući konvertiranje"</string> + <string name="transcode_default" msgid="3784803084573509491">"Pretpostavi da aplikacije podržavaju moderne formate"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Omogućivanje konvertiranja za aplikacije"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Pokrenute usluge"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Pregledajte i kontrolirajte pokrenute usluge"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napunit će se za <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napunit će se za <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Baterija je privremeno ograničena"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimiziranje radi zdravlja baterije"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index 33770fc1bdd8..e5d4bd15ce72 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Bekapcsolva. Koppintson ide a váltáshoz."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Alkalmazás készenléti állapota:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Médiaátkódolási beállítások"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Átkódolás letiltása"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Az átkódolás alapértelmezett beállításainak felülbírálása"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Átkódolás engedélyezése"</string> + <string name="transcode_default" msgid="3784803084573509491">"Annak feltételezése, hogy az alkalmazások támogatják a modern formátumokat"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Átkódolás engedélyezése az alkalmazásoknál"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Futó szolgáltatások"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"A jelenleg futó szolgáltatások megtekintése és vezérlése"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> van hátra a feltöltésből"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a feltöltésig"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akkumulátor ideiglenesen korlátozva"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akkumulátor-élettartam optimalizálása"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Ismeretlen"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Töltés"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Gyorstöltés"</string> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index 06d70f854f27..53eb766e3b17 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Ակտիվ է: Հպեք՝ փոխելու համար:"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Հավելվածի սպասման կարգավիճակ՝ <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Մեդիա ֆայլերի վերակոդավորման կարգավորումներ"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Անջատել վերակոդավորումը"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Չեղարկել վերակոդավորման կանխադրված կարգավորումները"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Միացնել վերակոդավորումը"</string> + <string name="transcode_default" msgid="3784803084573509491">"Ենթադրել, որ հավելվածներն աջակցում են ժամանակակից ձևաչափեր"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Միացնել վերակոդավորումը հավելվածների համար"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Աշխատող ծառայություններ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Դիտել և վերահսկել ընթացիկ աշխատող ծառայությունները"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> մինչև լիցքավորումը"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> մինչև լիցքավորումը"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Մարտկոցը ժամանակավորապես սահմանափակված է"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Օպտիմալացվում է"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Անհայտ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Լիցքավորում"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Արագ լիցքավորում"</string> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 4123d9e3b755..edce3c5d7336 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktif. Ketuk untuk beralih."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Status standby aplikasi:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Setelan transcoding media"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Menonaktifkan transcoding"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Ganti default transcoding"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Aktifkan transcoding"</string> + <string name="transcode_default" msgid="3784803084573509491">"Asumsikan aplikasi mendukung format modern"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Mengaktifkan transcoding untuk aplikasi"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Layanan yang sedang berjalan"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Melihat dan mengontrol layanan yang sedang berjalan"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Sisa <xliff:g id="TIME">%1$s</xliff:g> hingga terisi penuh"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi terisi penuh"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Daya baterai terbatas untuk sementara"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Mengoptimalkan untuk kesehatan baterai"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Mengisi daya"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengisi daya cepat"</string> diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml index 3b9bef872177..9e072ccdc8f7 100644 --- a/packages/SettingsLib/res/values-is/strings.xml +++ b/packages/SettingsLib/res/values-is/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Virkt. Ýttu til að breyta."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Biðstaða forrits: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Stillingar efnisumkóðunar"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Slökkva á umkóðun"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Hnekkja sjálfgefinni umkóðun"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Kveikja á umkóðun"</string> + <string name="transcode_default" msgid="3784803084573509491">"Gera ráð fyrir að forrit styðji nútímasnið"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Kveikja á umkóðun í forritum"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Þjónustur í gangi"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Skoða og stjórna þjónustum í gangi"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> að fullri hleðslu"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> að fullri hleðslu"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Rafhlaða takmörkuð tímabundið"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Fínstillir fyrir rafhlöðuendingu"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Óþekkt"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Í hleðslu"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hröð hleðsla"</string> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index 1ab6b24456f3..fc87d89b915d 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Attiva. Tocca per attivare/disattivare."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stato di standby dell\'app: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Impostazioni transcodifica contenuti multimediali"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Disattiva transcodifica"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Sostituisci impostazioni predefinite transcodifica"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Attiva transcodifica"</string> + <string name="transcode_default" msgid="3784803084573509491">"Presupponi che le app supportino i formati moderni"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Attiva transcodifica per le app"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Servizi in esecuzione"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualizza e controlla i servizi attualmente in esecuzione"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Tempo rimanente alla carica completa: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batteria momentaneamente limitata"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ottimizzazione per integrità batteria"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Sconosciuta"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"In carica"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ricarica veloce"</string> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index 15868d5fc997..b899b594e784 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"אפליקציה פעילה. הקש כדי להחליף מצב."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"אפליקציה במצב המתנה:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"הגדרות של המרת קידוד למדיה"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"השבתה של המרת קידוד"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"ביטול ברירות המחדל של המרת קידוד"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"הפעלת המרת קידוד"</string> + <string name="transcode_default" msgid="3784803084573509491">"הנחת העבודה היא שאפליקציות תומכות בפורמטים מודרניים"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"הפעלה של המרת קידוד לאפליקציות"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"שירותים פועלים"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"הצגת השירותים הפועלים כעת ושליטה בהם"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"נשארו <xliff:g id="TIME">%1$s</xliff:g> עד הטעינה"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד הטעינה"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - הסוללה מוגבלת באופן זמני"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> ﹣ מופעל מיטוב לשמירה על תקינות הסוללה"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"לא ידוע"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"בטעינה"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"הסוללה נטענת מהר"</string> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index 89ee98eeeb42..ded207d325a3 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"有効です。タップすると切り替わります。"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"アプリ スタンバイ状態: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"メディアのコード変換設定"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"コード変換を無効にする"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"デフォルトのコード変換をオーバーライド"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"コード変換を有効にする"</string> + <string name="transcode_default" msgid="3784803084573509491">"アプリによる最新形式のサポートを想定"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"アプリに対しコード変換を有効にする"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"実行中のサービス"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"現在実行中のサービスを表示して制御する"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"充電完了まであと <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電完了まで <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 電池の使用が一時的に制限されています"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - 電池の状態を最適化"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"急速充電中"</string> diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml index d1885789779a..2d89dc65cb60 100644 --- a/packages/SettingsLib/res/values-ka/strings.xml +++ b/packages/SettingsLib/res/values-ka/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"აქტიური. შეეხეთ გადასართავად."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"აპის მოლოდინის რეჟიმის მდგომარეობა:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"მედიის ტრანსკოდირების პარამეტრები"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ტრანსკოდირების გათიშვა"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"ტრანსკოდირების ნაგულისხმევების უგულებელყოფა"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"ტრანსკოდირების ჩართვა"</string> + <string name="transcode_default" msgid="3784803084573509491">"დაშვება, რომ აპებს აქვთ თანამედროვე ფორმატების მხარდაჭერა"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"ტრანსკოდირების ჩართვა აპებისთვის"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"მიმდინარე სერვისები"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ამჟამად მოქმედი სერვისების ნახვა და მართვა"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"დატენვამდე დარჩა <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> დატენვამდე"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> — ბატარეა დროებით შეზღუდულია"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> — ოპტიმიზაცია ბატარეის გამართულობისთვის"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"უცნობი"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"იტენება"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"სწრაფად იტენება"</string> diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml index 2bc1c4d20728..fa99529f84d4 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Белсенді. Ауыстырып қосу үшін түртіңіз."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Қолданбаның күту режимі: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Медиамазмұнды қайта кодтау параметрлері"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Қайта кодтауды өшіру"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Қайта қодтаудың әдепкі параметрлерін қайта анықтау"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Қайта кодтауды қосу"</string> + <string name="transcode_default" msgid="3784803084573509491">"Қолданбалар қазіргі заманғы форматтарды қолдайды делік"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Қолданбалар үшін қайта кодтауға рұқсат ету"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Қосылып тұрған қызметтер"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Қазір істеп тұрған қызметтерді көру және басқару"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Зарядталғанға дейін <xliff:g id="TIME">%1$s</xliff:g> қалды"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядталғанға дейін <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батарея жұмысы уақытша шектелген"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батареяның жұмыс істеу қабілеті оңтайландырылуда"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Белгісіз"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарядталуда"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Жылдам зарядталуда"</string> diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml index 7306cf8c5d3f..a2b5e014937e 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"សកម្ម។ ប៉ះដើម្បីបិទ/បើក។"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ស្ថានភាពមុខងារផ្អាកដំណើរការកម្មវិធី៖<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"ការកំណត់ការបំប្លែងកូដមេឌៀ"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"បិទការបំប្លែងកូដ"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"លុបពីលើលំនាំដើមនៃការបំប្លែងកូដ"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"បើកការបំប្លែងកូដ"</string> + <string name="transcode_default" msgid="3784803084573509491">"សន្មតថាកម្មវិធីអាចប្រើទម្រង់ទំនើបបាន"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"បើកការបំប្លែងកូដសម្រាប់កម្មវិធី"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"សេវាកម្មកំពុងដំណើរការ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"មើល និងគ្រប់គ្រងសេវាកម្មកំពុងដំណើរការបច្ចុប្បន្ន"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ទៀតទើបសាកថ្មពេញ"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ទៀតទើបសាកថ្មពេញ"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - បានដាក់កម្រិតថ្មជាបណ្ដោះអាសន្ន"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - កំពុងបង្កើនប្រសិទ្ធភាពគុណភាពថ្ម"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"មិនស្គាល់"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"កំពុងបញ្ចូលថ្ម"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"កំពុងសាកថ្មយ៉ាងឆាប់រហ័ស"</string> diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml index 0c1502ca620d..f37cf8be13f5 100644 --- a/packages/SettingsLib/res/values-kn/strings.xml +++ b/packages/SettingsLib/res/values-kn/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"ಸಕ್ರಿಯ. ಟಾಗಲ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ಅಪ್ಲಿಕೇಶನ್ ಸ್ಟ್ಯಾಂಡ್ಬೈ ಸ್ಥಿತಿ:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"ಮೀಡಿಯಾ ಟ್ರಾನ್ಸ್ಕೋಡಿಂಗ್ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ಟ್ರಾನ್ಸ್ಕೋಡಿಂಗ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string> + <!-- no translation found for transcode_user_control (6176368544817731314) --> + <skip /> + <!-- no translation found for transcode_enable_all (2411165920039166710) --> + <skip /> + <!-- no translation found for transcode_default (3784803084573509491) --> + <skip /> <string name="transcode_skip_apps" msgid="8249721984597390142">"ಆ್ಯಪ್ಗಳಿಗಾಗಿ ಟ್ರಾನ್ಸ್ಕೋಡಿಂಗ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"ರನ್ ಆಗುತ್ತಿರುವ ಸೇವೆಗಳು"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ಈಗ ರನ್ ಆಗುತ್ತಿರುವ ಸೇವೆಗಳನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ನಿಯಂತ್ರಿಸಿ"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ ಇದೆ"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯ ಬೇಕು"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಬ್ಯಾಟರಿ ತಾತ್ಕಾಲಿಕವಾಗಿ ಸೀಮಿತವಾಗಿದೆ"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಬ್ಯಾಟರಿಯ ಆರೋಗ್ಯಕ್ಕಾಗಿ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ಅಪರಿಚಿತ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ವೇಗದ ಚಾರ್ಜಿಂಗ್"</string> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index 13223440d098..73921c29815f 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"활성화되었습니다. 전환하려면 탭하세요."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"앱 대기 상태:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"미디어 트랜스코딩 설정"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"트랜스코딩 사용 중지"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"트랜스코딩 기본값 재정의"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"트랜스코딩 사용"</string> + <string name="transcode_default" msgid="3784803084573509491">"앱이 최신 형식을 지원하는 것으로 가정"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"앱 트랜스코딩 사용 설정"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"실행 중인 서비스"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"현재 실행 중인 서비스 보기 및 제어"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"충전 완료까지 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 충전 완료까지 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 일시적으로 배터리 사용 제한"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - 배터리 상태 최적화 중"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"알 수 없음"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"충전 중"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"고속 충전 중"</string> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index 9697aa70e44f..5e978ba7ac1b 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Иштеп турат. Өчүрүү үчүн басып коюңуз."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Көшүү режиминдеги колдонмонун абалы:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Медиа файлдарды транскоддоо жөндөөлөрү"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Транскоддоону өчүрүү"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Демейки жүргүзүлгөн транскоддоону өзгөртүп коюу"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Транскоддоо жүргүзүүнү иштетүү"</string> + <string name="transcode_default" msgid="3784803084573509491">"Колдонмолордо заманбап форматтар колдоого алынат"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Колдонмолорду транскоддоону күйгүзүү"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Иштеп жаткан кызматтар"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Учурда иштеп жаткан кызматтарды көрүп, көзөмөлдөп турасыз"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> кийин толук кубатталып бүтөт"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> кийин толук кубатталып бүтөт"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батареяны колдонуу убактлуу чектелген"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батареянын кубатын үнөмдөө иштетилди"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Белгисиз"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Кубатталууда"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ыкчам кубатталууда"</string> diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml index 720122262dcf..498cb25d96ff 100644 --- a/packages/SettingsLib/res/values-lo/strings.xml +++ b/packages/SettingsLib/res/values-lo/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"ນຳໃຊ້ຢູ່. ແຕະເພື່ອສັບປ່ຽນ."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ສະຖານະສະແຕນບາຍແອັບ:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"ການຕັ້ງຄ່າການປ່ຽນຮູບແບບລະຫັດມີເດຍ"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ປິດການນຳໃຊ້ການປ່ຽນຮູບແບບລະຫັດ"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"ຍົກເລີກຄ່າເລີ່ມຕົ້ນການປ່ຽນຮູບແບບລະຫັດ"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"ເປີດການນຳໃຊ້ການປ່ຽນຮູບແບບລະຫັດ"</string> + <string name="transcode_default" msgid="3784803084573509491">"ສົມມຸດວ່າແອັບຮອງຮັບຮູບແບບສະໄໝໃໝ່"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"ເປີດການນຳໃຊ້ການປ່ຽນຮູບແບບລະຫັດສຳລັບແອັບ"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"ບໍລິການທີ່ເຮັດວຽກຢູ່"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ເບິ່ງ ແລະຈັດການບໍລິການທີ່ກຳລັງເຮັດວຽກຢູ່ໃນປັດຈຸບັນ"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ຈຳກັດແບັດເຕີຣີຊົ່ວຄາວ"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ກຳລັງເພີ່ມປະສິດທິພາບເພື່ອສຸຂະພາບແບັດເຕີຣີ"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ບໍ່ຮູ້ຈັກ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ກຳລັງສາກໄຟ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ກຳລັງສາກໄຟດ່ວນ"</string> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index e62eeb2dbd97..c077268f3fad 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktyvi. Palieskite, kad perjungtumėte."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Programų budėjimo režimo būsena: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Medijos perkodavimo nustatymai"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Išjungti perkodavimą"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Perkodavimo numatytųjų nustatymų nepaisymas"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Perkodavimo įgalinimas"</string> + <string name="transcode_default" msgid="3784803084573509491">"Manoma, kad programos palaiko modernius formatus"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Įjungti programų perkodavimą"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Vykdomos paslaugos"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Žiūrėti ir valdyti dabar vykdomas paslaugas"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Iki visiškos įkrovos liko <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – iki visiškos įkrovos liko <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – akumuliatorius laikinai apribotas"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – optimizuoj. siekiant apsaugoti akum."</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nežinomas"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Kraunasi..."</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Greitai įkraunama"</string> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index 2f305612a5fc..d5755511f032 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktīva. Pieskarieties, lai pārslēgtu."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Lietotnes gaidstāves stāvoklis: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Multivides failu pārkodēšanas iestatījumi"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Atspējot pārkodēšanu"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Ignorēt pārkodēšanas noklusējuma iestatījumus"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Iespējot pārkodēšanu"</string> + <string name="transcode_default" msgid="3784803084573509491">"Pieņemt, ka lietotnēs tiek atbalstīti moderni formāti"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Iespējot pārkodēšanu noteiktām lietotnēm"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Aktīvie pakalpojumi"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Pašreiz darbojošos pakalpojumu skatīšana un vadība"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Vēl <xliff:g id="TIME">%1$s</xliff:g> līdz pilnai uzlādei"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>, akumulatora uzlāde pagaidām ierobežota"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: akumulatora darbības optimizēšana"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nezināms"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Uzlāde"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Notiek ātrā uzlāde"</string> diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml index 1936fe2d32a4..21dcb0285557 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Активно. Допрете за да смените."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Состојба на мирување на апликацијата: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Поставки за транскодирање аудиовизуелни содржини"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Оневозможи транскодирање"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Отфрли стандардни вредности за транскодирање"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Овозможи транскодирање"</string> + <string name="transcode_default" msgid="3784803084573509491">"Претпостави дека апликациите поддржуваат модерни формати"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Овозможете транскодирање за апликациите"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Активни услуги"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Погледнете и контролирајте услуги што се моментално активни"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Уште <xliff:g id="TIME">%1$s</xliff:g> до целосно полнење"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> до целосно полнење"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батеријата е привремено ограничена"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Се оптимизира за состојба на батерија"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Се полни"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо полнење"</string> diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml index de4a49a2ed06..97c22d569775 100644 --- a/packages/SettingsLib/res/values-ml/strings.xml +++ b/packages/SettingsLib/res/values-ml/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"സജീവം. മാറ്റുന്നതിന് ടാപ്പുചെയ്യുക."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ആപ്പ് സ്റ്റാൻഡ്ബൈ നില:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"മീഡിയ ട്രാൻസ്കോഡ് ചെയ്യൽ ക്രമീകരണം"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ട്രാൻസ്കോഡ് ചെയ്യൽ പ്രവർത്തനരഹിതമാക്കുക"</string> + <!-- no translation found for transcode_user_control (6176368544817731314) --> + <skip /> + <!-- no translation found for transcode_enable_all (2411165920039166710) --> + <skip /> + <!-- no translation found for transcode_default (3784803084573509491) --> + <skip /> <string name="transcode_skip_apps" msgid="8249721984597390142">"ആപ്പുകൾക്കായി ട്രാൻസ്കോഡ് ചെയ്യുന്നത് പ്രവർത്തനക്ഷമമാക്കുക"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"നിലവിൽ പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ കാണുക, നിയന്ത്രിക്കുക"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"പൂർണ്ണമായി ചാർജാവാൻ <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമായി ചാർജാവാൻ <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ബാറ്ററി താൽക്കാലം പരിമിതപ്പെടുത്തി"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ബാറ്ററി നില ഒപ്റ്റിമൈസ് ചെയ്യുന്നു"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"അജ്ഞാതം"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ചാർജ് ചെയ്യുന്നു"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"അതിവേഗ ചാർജിംഗ്"</string> diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml index dee8add685f9..8d1cc3391c5a 100644 --- a/packages/SettingsLib/res/values-mn/strings.xml +++ b/packages/SettingsLib/res/values-mn/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP тохируулга амжилтгүй"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Сүлжээний чанар муу байгаа тул холбогдож чадсангүй"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"WiFi холболт амжилтгүй"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Гэрчлэлийн асуудал"</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Баталгаажуулалтын асуудал"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"Холбогдож чадсангүй"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\'-д холбогдож чадсангүй"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Нууц үгийг шалгаад дахин оролдоно уу"</string> @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Идэвхтэй байна. Унтраах/асаахын тулд дарна уу."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Апп зогсолтын горимын төлөв:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Медиа хөрвүүлгийн тохиргоо"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Хөрвүүлгийг идэвхгүй болгох"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Хөрвүүлгийн өгөгдмөлийг дарах"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Хөрвүүлгийг идэвхжүүлэх"</string> + <string name="transcode_default" msgid="3784803084573509491">"Аппыг орчин үеийн форматыг дэмждэг гэж үздэг"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Аппуудад хөрвүүлгийг идэвхжүүлэх"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Ажиллаж байгаа үйлчилгээнүүд"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Одоо ажиллаж байгаа үйлчилгээнүүдийг харах болон хянах"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Цэнэглэх хүртэл үлдсэн <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - цэнэглэх хүртэл <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батарейг түр хугацаанд хязгаарласан"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батарейн чанарыг оновчилж байна"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Тодорхойгүй"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Цэнэглэж байна"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хурдан цэнэглэж байна"</string> @@ -534,7 +536,7 @@ <string name="user_add_user_item_title" msgid="2394272381086965029">"Хэрэглэгч"</string> <string name="user_add_profile_item_title" msgid="3111051717414643029">"Хязгаарлагдсан профайл"</string> <string name="user_add_user_title" msgid="5457079143694924885">"Шинэ хэрэглэгч нэмэх үү?"</string> - <string name="user_add_user_message_long" msgid="1527434966294733380">"Та нэмэлт хэрэглэгч үүсгэх замаар бусад хүмүүстэй энэ төхөөрөмжийг хуваалцаж болно. Хэрэглэгч тус бүр апп, ханын цаас болон бусад зүйлээ өөрчлөх боломжтой хувийн орон зайтай байдаг. Түүнчлэн хэрэглэгч нь бүх хэрэглэгчид нөлөөлөх боломжтой Wi-Fi зэрэг төхөөрөмжийн тохиргоог өөрчлөх боломжтой.\n\nХэрэв та шинэ хэрэглэгч нэмэх бол тухайн хүн хувийн орон зайгаа бүрдүүлэх ёстой.\n\nХэрэглэгч бүр бусад бүх хэрэглэгчийн өмнөөс апп шинэчилж болно. Хүртээмжийн тохиргоо болон үйлчилгээг шинэ хэрэглэгчид шилжүүлэх боломжгүй байж болзошгүй."</string> + <string name="user_add_user_message_long" msgid="1527434966294733380">"Та нэмэлт хэрэглэгч үүсгэх замаар бусад хүмүүстэй энэ төхөөрөмжийг хуваалцаж болно. Хэрэглэгч тус бүр апп, дэлгэцийн зураг болон бусад зүйлээ өөрчлөх боломжтой хувийн орон зайтай байдаг. Түүнчлэн хэрэглэгч нь бүх хэрэглэгчид нөлөөлөх боломжтой Wi-Fi зэрэг төхөөрөмжийн тохиргоог өөрчлөх боломжтой.\n\nХэрэв та шинэ хэрэглэгч нэмэх бол тухайн хүн хувийн орон зайгаа бүрдүүлэх ёстой.\n\nХэрэглэгч бүр бусад бүх хэрэглэгчийн өмнөөс апп шинэчилж болно. Хүртээмжийн тохиргоо болон үйлчилгээг шинэ хэрэглэгчид шилжүүлэх боломжгүй байж болзошгүй."</string> <string name="user_add_user_message_short" msgid="3295959985795716166">"Та шинэ хэрэглэгч нэмбэл тухайн хүн өөрийн профайлыг тохируулах шаардлагатай.\n\nАль ч хэрэглэгч бүх хэрэглэгчийн апп-уудыг шинэчлэх боломжтой."</string> <string name="user_setup_dialog_title" msgid="8037342066381939995">"Хэрэглэгчийг одоо тохируулах уу?"</string> <string name="user_setup_dialog_message" msgid="269931619868102841">"Хэрэглэгч төхөөрөмжийг авч өөрийн профайлыг тохируулах боломжтой эсэхийг шалгана уу"</string> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index 60ad68e42c09..c20888ea0af2 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"सक्रिय. टॉगल करण्यासाठी टॅप करा."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"अॅप स्टँडबाय स्थिती: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"मीडिया ट्रान्सकोडिंगची सेटिंग्ज"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ट्रान्सकोडिंग बंद करा"</string> + <!-- no translation found for transcode_user_control (6176368544817731314) --> + <skip /> + <!-- no translation found for transcode_enable_all (2411165920039166710) --> + <skip /> + <!-- no translation found for transcode_default (3784803084573509491) --> + <skip /> <string name="transcode_skip_apps" msgid="8249721984597390142">"ॲप्ससाठी ट्रान्सकोडिंग सुरू करा"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"सुरू सेवा"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"सध्या सुरू असलेल्या सेवा पहा आणि नियंत्रित करा"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> पर्यंत पूर्ण चार्ज होईल"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पर्यंत पूर्ण चार्ज होईल"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - बॅटरी तात्पुरती मर्यादित आहे"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - बॅटरीची क्षमता वाढवण्यासाठी ऑप्टिमाइझ करत आहे"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज होत आहे"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"वेगाने चार्ज होत आहे"</string> diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml index e4d591207937..76840a52b0a2 100644 --- a/packages/SettingsLib/res/values-ms/strings.xml +++ b/packages/SettingsLib/res/values-ms/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktif. Ketik untuk menogol."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Keadaan tunggu sedia apl:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Tetapan transpengekodan media"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Lumpuhkan transpengekodan"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Batalkan transpengekodan lalai"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Dayakan transpengekodan"</string> + <string name="transcode_default" msgid="3784803084573509491">"Mengambil alih sokongan apl format moden"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Dayakan transpengekodan untuk apl"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Perkhidmatan dijalankan"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Lihat dan kawal perkhidmatan yang sedang dijalankan"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> lagi sehingga dicas penuh"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga dicas"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Bateri terhad untuk sementara"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengoptimuman untuk kesihatan bateri"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Mengecas"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengecas dgn cepat"</string> diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml index 09a8bf87700b..377e49da5031 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP ပြုပြင်ခြင်း မအောင်မြင်ပါ"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"ကွန်ရက်ချိတ်ဆက်မှု အားနည်းသည့်အတွက် ချိတ်ဆက်ထားခြင်း မရှိပါ"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"WiFi ချိတ်ဆက်မှု မအောင်မြင်ပါ"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"စစ်မှန်ကြောင်းအတည်ပြုရန်၌ ပြသနာရှိခြင်း"</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"အထောက်အထားစိစစ်မှု ပြဿနာ"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"ချိတ်ဆက်၍ မရပါ"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\' နှင့် ချိတ်ဆက်၍ မရပါ"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"စကားဝှက်ကို စစ်ဆေးပြီး ထပ်လုပ်ကြည့်ပါ"</string> @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"ပွင့်နေသည်။ ပြောင်းရန်တို့ပါ။"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"အက်ပ်ကို အရန်သင့်ထားရှိခြင်း အခြေအနေ-<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"မီဒီယာအမျိုးအစားပြောင်းခြင်း ဆက်တင်များ"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"အမျိုးအစားပြောင်းခြင်းကို ပိတ်ရန်"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"အမျိုးအစားပြောင်းခြင်း၏ မူရင်းဆက်တင်များကို အစားထိုးရန်"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"အမျိုးအစားပြောင်းခြင်းကို ဖွင့်ရန်"</string> + <string name="transcode_default" msgid="3784803084573509491">"ဤအက်ပ်များက ဖော်မက်အသစ်များကို ပံ့ပိုးသည်"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"အက်ပ်များအတွက် အမျိုးအစားပြောင်းခြင်းကို ဖွင့်ရန်"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"အလုပ်လုပ်နေသောဝန်ဆောင်မှုများ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"လက်ရှိ ဝန်ဆောင်မှုများကို ကြည့်ရှု ထိန်းသိမ်းသည်"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"အားပြည့်ရန် <xliff:g id="TIME">%1$s</xliff:g> ကျန်သည်"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားပြည့်ရန် <xliff:g id="TIME">%2$s</xliff:g> ကျန်သည်"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ဘက်ထရီ ယာယီကန့်သတ်ထားသည်"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ဘက်ထရီအခြေအနေကို အကောင်းဆုံးဖြစ်အောင် လုပ်နေသည်"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"မသိ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"အားသွင်းနေပါသည်"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"အမြန် အားသွင်းနေသည်"</string> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index d1af28940f1b..db931218567f 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -34,7 +34,7 @@ <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Sjekk passordet og prøv igjen"</string> <string name="wifi_not_in_range" msgid="1541760821805777772">"Utenfor område"</string> <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"Kobler ikke til automatisk"</string> - <string name="wifi_no_internet" msgid="1774198889176926299">"Ingen Internett-tilgang"</string> + <string name="wifi_no_internet" msgid="1774198889176926299">"Ingen internettilgang"</string> <string name="saved_network" msgid="7143698034077223645">"Lagret av <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="connected_via_network_scorer" msgid="7665725527352893558">"Automatisk tilkoblet via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"Automatisk tilkoblet via leverandør av nettverksvurdering"</string> @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Trykk for å slå av/på."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Hvilemodus:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Innstillinger for omkoding av medier"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Deaktiver omkoding"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Overstyr omkodingsstandarder"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Slå på omkoding"</string> + <string name="transcode_default" msgid="3784803084573509491">"Anta at apper støtter moderne formater"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktiver omkoding for apper"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Aktive tjenester"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Se og kontrollér tjenester som kjører"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> til batteriet er fulladet"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til batteriet er fulladet"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Batteriet er midlertidig begrenset"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimaliserer batteritilstanden"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Ukjent"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Lader"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Lader raskt"</string> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index 0c6114b9e220..25a2919f0958 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"सक्रिय। टगल गर्न ट्याप गर्नुहोस्।"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"एपको स्ट्यान्डबाई अवस्था:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"मिडिया ट्रान्सकोडिङ सेटिङ"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ट्रान्सकोडिङ अफ गर्नुहोस्"</string> + <!-- no translation found for transcode_user_control (6176368544817731314) --> + <skip /> + <!-- no translation found for transcode_enable_all (2411165920039166710) --> + <skip /> + <!-- no translation found for transcode_default (3784803084573509491) --> + <skip /> <string name="transcode_skip_apps" msgid="8249721984597390142">"एपहरूमा ट्रान्सकोडिङ अन गर्नुहोस्"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"चलिरहेका सेवाहरू"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"हाल चालु भइरहेका सेवाहरू हेर्नुहोस् र नियन्त्रण गर्नुहोस्"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"पूर्ण चार्ज हुन <xliff:g id="TIME">%1$s</xliff:g> बाँकी"</string> <string name="power_charging_duration" msgid="5005740040558984057">"पूर्ण चार्ज हुन <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> लाग्छ"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - केही समयका लागि ब्याट्री प्रयोग सीमित गरिएको छ"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ब्याट्री लामो समयसम्म टिक्ने बनाउन अप्टिमाइज गरिँदै छ"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हुँदै"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"द्रुत गतिमा चार्ज गरिँदै"</string> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index a409756e5b5f..0f2cc6ff66e8 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Actief. Tik om te schakelen."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stand-bystatus app: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Instellingen voor mediatranscodering"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Transcodering uitschakelen"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Standaardwaarden voor transcodering overschrijven"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Transcodering inschakelen"</string> + <string name="transcode_default" msgid="3784803084573509491">"Aannemen dat apps moderne indelingen ondersteunen"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Transcodering inschakelen voor apps"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Actieve services"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Services die momenteel actief zijn, weergeven en beheren"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Nog <xliff:g id="TIME">%1$s</xliff:g> tot opgeladen"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot opgeladen"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batterij tijdelijk beperkt"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Optimaliseren voor batterijduur"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Opladen"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Snel opladen"</string> diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml index 0a0eeff6de60..040ddddf96f7 100644 --- a/packages/SettingsLib/res/values-or/strings.xml +++ b/packages/SettingsLib/res/values-or/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP କନଫିଗରେଶନ ବିଫଳ ହୋଇଛି"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"ନିମ୍ନ ମାନର ନେଟ୍ୱର୍କ କାରଣରୁ ସଂଯୁକ୍ତ ହୋଇନାହିଁ"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"ୱାଇଫାଇ ସଂଯୋଗ ବିଫଳ ହୋଇଛି"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"ସତ୍ୟାପନରେ ସମସ୍ୟା"</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"ପ୍ରମାଣୀକରଣରେ ସମସ୍ୟା"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"ସଂଯୋଗ କରିପାରିବ ନାହିଁ"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\' ସହିତ ସଂଯୁକ୍ତ ହୋଇପାରୁନାହିଁ"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"ପାସ୍ୱର୍ଡ ଯାଞ୍ଚ କରନ୍ତୁ ଏବଂ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string> @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"ସକ୍ରିୟ। ବଦଳାଇବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ଆପ୍ ଷ୍ଟାଣ୍ଡବାଏ ଅବସ୍ଥା:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"ମିଡିଆ ଟ୍ରାନ୍ସକୋଡିଂ ସେଟିଂସ୍"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ଟ୍ରାନ୍ସକୋଡିଂ ଅକ୍ଷମ କରନ୍ତୁ"</string> + <!-- no translation found for transcode_user_control (6176368544817731314) --> + <skip /> + <!-- no translation found for transcode_enable_all (2411165920039166710) --> + <skip /> + <!-- no translation found for transcode_default (3784803084573509491) --> + <skip /> <string name="transcode_skip_apps" msgid="8249721984597390142">"ଆପଗୁଡ଼ିକ ପାଇଁ ଟ୍ରାନ୍ସକୋଡିଂ ସକ୍ଷମ କରନ୍ତୁ"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"ଚାଲୁଥିବା ସେବାଗୁଡ଼ିକ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ଏବେ ଚାଲୁଥିବା ସେବାଗୁଡ଼ିକୁ ଦେଖନ୍ତୁ ଓ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ଚାର୍ଜ ହେବା ପାଇଁ <xliff:g id="TIME">%1$s</xliff:g> ବାକି ଅଛି"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ଚାର୍ଜ ହେବା ପର୍ଯ୍ୟନ୍ତ"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ବ୍ୟାଟେରୀ ଅସ୍ଥାୟୀ ଭାବେ ସୀମିତ ଅଛି"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ବ୍ୟାଟେରୀ ହେଲ୍ଥ ପାଇଁ ଅପ୍ଟିମାଇଜ୍ ହେଉଛି"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ଅଜ୍ଞାତ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ଚାର୍ଜ ହେଉଛି"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ଶୀଘ୍ର ଚାର୍ଜ ହେଉଛି"</string> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index c9c37d922537..e6adff30b2cf 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"ਕਿਰਿਆਸ਼ੀਲ। ਟੌਗਲ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ਐਪ ਸਟੈਂਡਬਾਈ ਸਥਿਤੀ:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"ਮੀਡੀਆ ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਸੈਟਿੰਗਾਂ"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਬੰਦ ਕਰੋ"</string> + <!-- no translation found for transcode_user_control (6176368544817731314) --> + <skip /> + <!-- no translation found for transcode_enable_all (2411165920039166710) --> + <skip /> + <!-- no translation found for transcode_default (3784803084573509491) --> + <skip /> <string name="transcode_skip_apps" msgid="8249721984597390142">"ਐਪਾਂ ਲਈ ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਚਾਲੂ ਕਰੋ"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ਇਸ ਵੇਲੇ ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ ਦੇਖੋ ਅਤੇ ਇਹਨਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰੋ"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਤੱਕ ਚਾਰਜ ਹੋ ਜਾਵੇਗੀ"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਬੈਟਰੀ ਕੁਝ ਸਮੇਂ ਲਈ ਸੀਮਤ"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਬੈਟਰੀ ਸਥਿਤੀ ਲਈ ਅਨੁਕੂਲ ਬਣਾਇਆ ਜਾ ਰਿਹਾ"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ਅਗਿਆਤ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ਤੇਜ਼ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index e894c2cbc34c..5690e748c4cd 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktywna. Dotknij, by zmienić."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stan aplikacji w trybie czuwania: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Ustawienia transkodowania multimediów"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Wyłącz transkodowanie"</string> + <!-- no translation found for transcode_user_control (6176368544817731314) --> + <skip /> + <!-- no translation found for transcode_enable_all (2411165920039166710) --> + <skip /> + <!-- no translation found for transcode_default (3784803084573509491) --> + <skip /> <string name="transcode_skip_apps" msgid="8249721984597390142">"Włącz transkodowanie dla aplikacji"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Uruchomione usługi"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Wyświetl obecnie uruchomione usługi i nimi zarządzaj"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Do naładowania <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – do naładowania <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – bateria tymczasowo ograniczona"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optymalizuję, by utrzymać baterię w dobrym stanie"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nieznane"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Ładowanie"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Szybkie ładowanie"</string> diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index acaabc793970..a0ddcf226a0d 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Ativo. Tocar para alternar."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado em espera do app:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Configurações de transcodificação de mídia"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Desativar transcodificação"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Substituir os padrões de transcodificação"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Ativar transcodificação"</string> + <string name="transcode_default" msgid="3784803084573509491">"Considerar que os apps são compatíveis com formatos modernos"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Ativar transcodificação para apps"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Serviços em execução"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualizar e controlar os serviços em execução no momento"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Tempo restante até a carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: bateria limitada temporariamente"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: otimizando para integridade da bateria"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 2c1a9678f158..adaed743477e 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Ativo. Toque para ativar/desativar."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado do Modo de espera das apps:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Definições da transcodificação de multimédia"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Desativar a transcodificação"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Substituir as predefinições da transcodificação"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Ativar a transcodificação"</string> + <string name="transcode_default" msgid="3784803084573509491">"Assumir que as apps suportam formatos modernos"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Ative a transcodificação para apps"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Serviços em execução"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ver e controlar os serviços actualmente em execução"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Falta(m) <xliff:g id="TIME">%1$s</xliff:g> até ficar carregada"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar carregada"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Bateria limitada temporariamente."</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – A otimizar o estado da bateria"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"A carregar"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregamento rápido"</string> diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index acaabc793970..a0ddcf226a0d 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Ativo. Tocar para alternar."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado em espera do app:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Configurações de transcodificação de mídia"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Desativar transcodificação"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Substituir os padrões de transcodificação"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Ativar transcodificação"</string> + <string name="transcode_default" msgid="3784803084573509491">"Considerar que os apps são compatíveis com formatos modernos"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Ativar transcodificação para apps"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Serviços em execução"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualizar e controlar os serviços em execução no momento"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Tempo restante até a carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: bateria limitada temporariamente"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: otimizando para integridade da bateria"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index 57a0454f3465..266dff2fa81b 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Activă. Atingeți pentru a comuta."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stare Standby aplicații: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Setări pentru transcodarea conținutului media"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Dezactivați transcodarea"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Modificați setările prestabilite de transcodare"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Activați transcodarea"</string> + <string name="transcode_default" msgid="3784803084573509491">"Presupuneți că aplicațiile acceptă formatele moderne"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Activați transcodarea pentru aplicații"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Servicii în curs de funcționare"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Vedeți și controlați serviciile care funcționează în prezent"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Au mai rămas <xliff:g id="TIME">%1$s</xliff:g> până la încărcare"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> până la încărcare"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – baterie limitată temporar"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Se fac optimizări pentru buna funcționare a bateriei"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Necunoscut"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Se încarcă"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Se încarcă rapid"</string> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index 09b8de04388b..ca20baee55b1 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Включено. Нажмите, чтобы отключить."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Статус приложения в режиме ожидания:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Настройки перекодирования медиафайлов"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Отключить перекодирование"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Переопределять настройки транскодирования по умолчанию"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Включить перекодирование"</string> + <string name="transcode_default" msgid="3784803084573509491">"Считать, что приложения поддерживают современные форматы кодирования"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Включить перекодирование для приложений"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Работающие службы"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Просмотр и управление работающими службами"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> до полной зарядки"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> • Уровень заряда временно ограничен"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"Оптимизация для увеличения срока службы батареи (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Идет зарядка"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Быстрая зарядка"</string> diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml index d36140f66b54..da69b813ee88 100644 --- a/packages/SettingsLib/res/values-si/strings.xml +++ b/packages/SettingsLib/res/values-si/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"සක්රියයි. ටොගල කිරීමට තට්ටු කරන්න."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"යෙදුම් පොරොත්තු තත්ත්වය:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"මාධ්ය ට්රාන්ස්කෝඩින් සැකසීම්"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ට්රාන්ස්කෝඩින් අබල කරන්න"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"ට්රාන්ස්කෝඩින් පෙරනිමි ප්රතික්ෂේප කරන්න"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"ට්රාන්ස්කෝඩින් සබල කරන්න"</string> + <string name="transcode_default" msgid="3784803084573509491">"යෙදුම් නවීන ආකෘති සඳහා සහාය දක්වයි යැයි උපකල්පනය කරමු"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"යෙදුම් සඳහා ට්රාන්ස්කෝඩින් සබල කරන්න"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"ධාවනය වන සේවා"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"දැනට ධාවනය වන සේවා බලන්න සහ පාලනය කරන්න"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ආරෝපණය වන තෙක් <xliff:g id="TIME">%1$s</xliff:g> ඇත"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආරෝපණය වන තෙක් <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - බැටරිය තාවකාලිකව සීමිතයි"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - බැටරි සෞඛ්යය සඳහා ප්රශස්ත කරමින්"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"නොදනී"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ආරෝපණය වෙමින්"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ශීඝ්ර ආරෝපණය"</string> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index 096e95e7050b..b428b421ad32 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Zlyhanie konfigurácie adresy IP"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Nepripojené z dôvodu siete nízkej kvality"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Zlyhanie pripojenia Wi‑Fi"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problém s overením totožnosti"</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problém s overením"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"Nedá sa pripojiť"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"K sieti <xliff:g id="AP_NAME">%1$s</xliff:g> sa nedá pripojiť"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Skontrolujte heslo a skúste to znova"</string> @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktívne. Prepnite klepnutím."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stav pohotovostného režimu aplikácie: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Nastavenia prekódovania médií"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Vypnúť prekódovanie"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Prepísať predvolené nastavenia prekódovania"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Povoliť prekódovanie"</string> + <string name="transcode_default" msgid="3784803084573509491">"Prepdokladať, že aplikácie podporujú moderné formáty"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Zapnúť prekódovanie aplikácií"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Spustené služby"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Zobrazovať a riadiť aktuálne spustené služby"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Zostávajúci čas do úplného nabitia: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Batéria je dočasne obmedzená"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimalizácia stavu batérie"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznáme"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíja sa"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rýchle nabíjanie"</string> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index 345fa36d3bd6..3ba31fa1eed5 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivno. Dotaknite se za preklop."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stanje pripravljenosti aplikacije: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Nastavitve prekodiranja predstavnosti"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Onemogočanje prekodiranja"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Preglasi privzete nastavitve prekodiranja"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Omogoči prekodiranje"</string> + <string name="transcode_default" msgid="3784803084573509491">"Aplikacije naj bi podpirale sodobne oblike zapisov"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Omogočanje prekodiranja za aplikacije"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Zagnane storitve"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Preglejte in nadzorujte storitve, ki so trenutno zagnane"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Še <xliff:g id="TIME">%1$s</xliff:g> do polne napolnjenosti"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do polne napolnjenosti"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – baterija je začasno omejena"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimizacija za ohran. zmog. baterije"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznano"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Polnjenje"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hitro polnjenje"</string> diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml index 3953a6a4f6e0..15cbb7439c64 100644 --- a/packages/SettingsLib/res/values-sq/strings.xml +++ b/packages/SettingsLib/res/values-sq/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Trokit për ta ndryshuar."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Gjendja e gatishmërisë e aplikacionit:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Cilësimet e transkodimit të multimediave"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Çaktivizo transkodimin"</string> + <!-- no translation found for transcode_user_control (6176368544817731314) --> + <skip /> + <!-- no translation found for transcode_enable_all (2411165920039166710) --> + <skip /> + <!-- no translation found for transcode_default (3784803084573509491) --> + <skip /> <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktivizo transkodimin për aplikacionet"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Shërbimet në ekzekutim"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Shiko dhe kontrollo shërbimet që po ekzekutohen aktualisht"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> të mbetura deri në karikim"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të karikohet"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Bateria e kufizuar përkohësisht"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Po optimizohet për integritetin e baterisë"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"I panjohur"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Po karikohet"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Po ngarkon me shpejtësi"</string> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index 70b287933c93..c3371829361d 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Активна. Додирните да бисте је деактивирали."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Стање приправности апликације: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Подешавања транскодирања медија"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Онемогући транскодирање"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Замени подразумевана подешавања транскодирања"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Омогући транскодирање"</string> + <string name="transcode_default" msgid="3784803084573509491">"Подразумевај да апликације подржавају модерне формате"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Омогућите транскодирање за апликације"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Покренуте услуге"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Приказ и контрола тренутно покренутих услуга"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Напуниће се за <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – напуниће се за <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – батерија је тренутно ограничена"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Оптимизује се ради стања батерије"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Пуни се"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо се пуни"</string> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index f466e882c2fc..2bf9785f67d4 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Tryck om du vill inaktivera."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Status för strömsparfunktion för appar:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Inställningar för medieomkodning"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Inaktivera omkodning"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Åsidosätta standardinställningar för omkodning"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Aktivera omkodning"</string> + <string name="transcode_default" msgid="3784803084573509491">"Anta att appar har stöd för moderna format"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktivera omkodning för appar"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Aktiva tjänster"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Visa och styr aktiva tjänster"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> kvar till full laddning"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till full laddning"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – batteriet är tillfälligt begränsat"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimerar batteriets livslängd"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Okänd"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Laddar"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laddas snabbt"</string> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index e1060fec2a66..610bfeefc743 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Inatumika. Gusa ili ugeuze."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Hali ya kisitisha programu:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Mipangilio ya kubadilisha muundo wa faili ya maudhui"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Zima ubadilishaji muundo wa faili"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Batilisha chaguomsingi za kubadilisha miundo ya faili"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Ruhusu ubadilishaji wa miundo ya faili"</string> + <string name="transcode_default" msgid="3784803084573509491">"Chukulia kuwa programu zinatumia miundo ya kisasa"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Washa ubadilishaji muundo wa faili kwenye programu"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Huduma zinazoendeshwa"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Onyesha na udhibiti huduma zinazoendeshwa kwa sasa"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Imebakisha <xliff:g id="TIME">%1$s</xliff:g> ijae chaji"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ijae chaji"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Betri imedhibitiwa kwa muda"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Inaboresha muda wa kutumia betri"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Haijulikani"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Inachaji"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Inachaji kwa kasi"</string> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index ba98d79ff7e4..7d77967e0daf 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"செயலில் உள்ளது. மாற்ற, தட்டவும்."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"காத்திருப்பில் உள்ள ஆப்ஸின் நிலை:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"மீடியா குறிமாற்ற அமைப்புகள்"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"குறிமாற்றத்தை முடக்கு"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"இயல்புநிலை குறிமாற்றங்களை மீறிச் செயல்படு"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"குறிமாற்றத்தை இயக்கு"</string> + <string name="transcode_default" msgid="3784803084573509491">"ஆப்ஸ் மாடர்ன் வடிவங்களை ஆதரிக்கும்படி அமை"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"ஆப்ஸுக்குக் குறிமாற்றத்தை இயக்கு"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"இயங்கும் சேவைகள்"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"தற்போது இயக்கத்தில் இருக்கும் சேவைகளைப் பார்த்து கட்டுப்படுத்து"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"முழு சார்ஜாக <xliff:g id="TIME">%1$s</xliff:g> ஆகும்"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - முழு சார்ஜாக <xliff:g id="TIME">%2$s</xliff:g> ஆகும்"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>-பேட்டரி தற்காலிகக் கட்டுப்பாட்டிலுள்ளது"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - பேட்டரியின் ஆயுளை மேம்படுத்துகிறது"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"அறியப்படாத"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"சார்ஜ் ஆகிறது"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"வேகமாக சார்ஜாகிறது"</string> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 0b93979dbd07..f24caecc453f 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"సక్రియంగా ఉంది. టోగుల్ చేయడానికి నొక్కండి."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"యాప్ స్టాండ్బై స్థితి:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"మీడియా ట్రాన్స్కోడింగ్ సెట్టింగ్లు"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ట్రాన్స్కోడింగ్ను డిజేబుల్ చేయండి"</string> + <!-- no translation found for transcode_user_control (6176368544817731314) --> + <skip /> + <!-- no translation found for transcode_enable_all (2411165920039166710) --> + <skip /> + <!-- no translation found for transcode_default (3784803084573509491) --> + <skip /> <string name="transcode_skip_apps" msgid="8249721984597390142">"యాప్ల కోసం ట్రాన్స్కోడింగ్ను ఎనేబుల్ చేయండి"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"అమలులో ఉన్న సేవలు"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ప్రస్తుతం అమలులో ఉన్న సేవలను వీక్షించండి మరియు నియంత్రించండి"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ఛార్జ్ అవ్వడానికి <xliff:g id="TIME">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జ్ అవ్వడానికి <xliff:g id="TIME">%2$s</xliff:g> పడుతుంది"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> -బ్యాటరీ తాత్కాలికంగా పరిమితం చేయబడింది"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - బ్యాటరీ స్థితిని ఆప్టిమైజ్ చేయడం కోసం"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"తెలియదు"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ఛార్జ్ అవుతోంది"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"వేగవంతమైన ఛార్జింగ్"</string> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index a31e14611bf6..2c019983f639 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"ใช้งานอยู่ แตะเพื่อสลับ"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"สถานะการสแตนด์บายของแอป:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"การตั้งค่าการแปลงสื่อ"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ปิดใช้การแปลง"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"ลบล้างค่าเริ่มต้นของการแปลง"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"เปิดใช้การแปลง"</string> + <string name="transcode_default" msgid="3784803084573509491">"ถือว่าแอปรองรับรูปแบบสมัยใหม่"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"เปิดใช้การแปลงสำหรับแอป"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"บริการที่ทำงานอยู่"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ดูและควบคุมบริการที่ทำงานอยู่"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"เหลือ <xliff:g id="TIME">%1$s</xliff:g> จนกว่าจะชาร์จเต็ม"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะชาร์จ"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - การชาร์จแบตเตอรี่จำกัดชั่วคราว"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - กำลังเพิ่มประสิทธิภาพแบตเตอรี่"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ไม่ทราบ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"กำลังชาร์จ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"กำลังชาร์จอย่างเร็ว"</string> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index bbb77790e68a..54ba90ef4b31 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Pagkabigo ng Configuration ng IP"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Hindi nakakonekta dahil mababa ang kalidad ng network"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Pagkabigo ng Koneksyon sa WiFi"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problema sa pagpapatotoo"</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problema sa pag-authenticate"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"Hindi makakonekta"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Hindi makakonekta sa \'<xliff:g id="AP_NAME">%1$s</xliff:g>\'"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Suriin ang password at subukang muli"</string> @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktibo. I-tap upang i-toggle."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Status ng app standby:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Mga setting ng pag-transcode ng media"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"I-disable ang pag-transcode"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"I-override ang mga default ng pagta-transcode"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"I-enable ang pagta-transcode"</string> + <string name="transcode_default" msgid="3784803084573509491">"Ipagpalagay na sinusuportahan ng mga app ang mga modernong format"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"I-enable ang pag-transcode para sa mga app"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Mga tumatakbong serbisyo"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Tingnan at kontrolin ang mga kasalukuyang tumatakbong serbisyo"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ang natitira bago matapos mag-charge"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hanggang matapos mag-charge"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pansamantalang limitado ang baterya"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ino-optimize para sa tagal ng baterya"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Hindi Kilala"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Nagcha-charge"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mabilis na charge"</string> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index fba7f41bbbf5..942834f230eb 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Etkin. Geçiş yapmak için dokunun."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Uygulamayı beklemeye alma durumu: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Medya kod dönüştürme ayarları"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Kod dönüştürmeyi devre dışı bırak"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Kod dönüştürme varsayılanlarını geçersiz kıl"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Kod dönüştürmeyi etkinleştir"</string> + <string name="transcode_default" msgid="3784803084573509491">"Uygulamaların modern biçimleri desteklediğini varsay"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Uygulamalar için kod dönüştürmeyi etkinleştir"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Çalışan hizmetler"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Şu anda çalışan hizmetleri görüntüle ve denetle"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Şarj olmaya <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - şarj olmaya <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pil geçici olarak sınırlı"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pil sağlığı için optimize ediliyor"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Bilinmiyor"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Şarj oluyor"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hızlı şarj oluyor"</string> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index b633752d28a9..f6063f8147ba 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Активний додаток. Торкніться, щоб дезактивувати."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Режим очікування: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Налаштування перекодування медіафайлів"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Вимкнути перекодування"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Замінити стандартні налаштування перекодування"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Увімкнути перекодування"</string> + <string name="transcode_default" msgid="3784803084573509491">"Вважати, що додатки підтримують сучасні формати"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Увімкнути перекодування додатків"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Запущені сервіси"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Переглянути й налаштувати запущені сервіси"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> до повного заряду"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного заряду"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – дані акумулятора тимчасово недоступні"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – стан акумулятора оптимізується"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Невідомо"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Заряджається"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Швидке заряджання"</string> diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml index b4d8ad2576bd..5d754373a5a4 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"فعال۔ ٹوگل کرنے کیلئے تھپتھپائیں۔"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ایپ اسٹینڈ بائی کی حالت:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"میڈیا ٹرانسکوڈنگ کی ترتیبات"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ٹرانسکوڈنگ غیر فعال کریں"</string> + <!-- no translation found for transcode_user_control (6176368544817731314) --> + <skip /> + <!-- no translation found for transcode_enable_all (2411165920039166710) --> + <skip /> + <!-- no translation found for transcode_default (3784803084573509491) --> + <skip /> <string name="transcode_skip_apps" msgid="8249721984597390142">"ایپس کے لئے ٹرانسکوڈنگ فعال کریں"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"چل رہی سروسز"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"فی الحال چل رہی سروسز دیکھیں اور انہیں کنٹرول کریں"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"چارج ہونے میں <xliff:g id="TIME">%1$s</xliff:g> باقی"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> چارج ہونے تک"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - بیٹری عارضی طور پر محدود ہے"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - بیٹری کی صحت کیلئے بہتر بنایا جا رہا ہے"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"نامعلوم"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"چارج ہو رہا ہے"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"تیزی سے چارج ہو رہا ہے"</string> diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml index 2f06fcfd5dee..0770dcc42bc8 100644 --- a/packages/SettingsLib/res/values-uz/arrays.xml +++ b/packages/SettingsLib/res/values-uz/arrays.xml @@ -25,7 +25,7 @@ <item msgid="3288373008277313483">"Qidiruv…"</item> <item msgid="6050951078202663628">"Ulanmoqda…"</item> <item msgid="8356618438494652335">"Tasdiqdan o‘tilmoqda…"</item> - <item msgid="2837871868181677206">"IP manzil o‘zlashtirilmoqda…"</item> + <item msgid="2837871868181677206">"IP manzil olinmoqda…"</item> <item msgid="4613015005934755724">"Ulangan"</item> <item msgid="3763530049995655072">"Muzlatildi"</item> <item msgid="7852381437933824454">"Uzilmoqda…"</item> diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml index 5bb422ecf96a..f1fc8ddcc5ea 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP manzilini sozlab bo‘lmadi"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Sifatsiz tarmoq sababli ulanib bo‘lmadi"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Wi-Fi ulanishini o‘rnatib bo‘lmadi"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Tasdiqdan o‘tishda muammo"</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Tekshiruvda muammo"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"Tarmoqqa ulanilmadi"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"“<xliff:g id="AP_NAME">%1$s</xliff:g>” nomli tarmoqqa ulanilmadi"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Parolni tekshirib, qaytadan urining"</string> @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Faol. O‘zgartirish uchun bu yerga bosing."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Kutish rejimi holati: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Media transkripsiyasi sozlamalari"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Transkripsiyani faolsizlantirish"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Transkripsiya parametrlarini almashtirish"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Transkripsiyasini yoqish"</string> + <string name="transcode_default" msgid="3784803084573509491">"Ilovalar zamonaviy kodlash formatlarini qoʻllab-quvvatlaydi deb hisoblash"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Ilovalar uchun transkripsiyani yoqish"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Ishlab turgan ilovalar"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ishlab turgan ilovalarni ko‘rish va boshqarish"</string> @@ -432,8 +434,8 @@ <skip /> <string name="power_discharge_by_enhanced" msgid="563438403581662942">"Joriy holatda taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_discharge_by_only_enhanced" msgid="3268796172652988877">"Joriy holatda taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi"</string> - <string name="power_discharge_by" msgid="4113180890060388350">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> - <string name="power_discharge_by_only" msgid="92545648425937000">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi"</string> + <string name="power_discharge_by" msgid="4113180890060388350">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha yetadi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> + <string name="power_discharge_by_only" msgid="92545648425937000">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha yetadi"</string> <string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> gacha"</string> <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Batareya quvvati tugash vaqti: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"<xliff:g id="THRESHOLD">%1$s</xliff:g>dan kam qoldi"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ichida toʻladi"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> ichida toʻladi"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Quvvat darajasi vaqtincha cheklangan"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Batareya quvvati muvozanatlanmoqda"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Noma’lum"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Quvvat olmoqda"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Tezkor quvvat olmoqda"</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index 0acf9418b718..910fa2634f8c 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Hiện hoạt. Nhấn để chuyển đổi."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Trạng thái chờ ứng dụng:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Cài đặt chuyển mã nội dung nghe nhìn"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Tắt tùy chọn chuyển mã"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Ghi đè tùy chọn chuyển mã mặc định"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Bật tính năng chuyển mã"</string> + <string name="transcode_default" msgid="3784803084573509491">"Giả định rằng các ứng dụng hỗ trợ định dạng hiện đại"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Bật tùy chọn chuyển mã cho ứng dụng"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Các dịch vụ đang chạy"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Xem và kiểm soát các dịch vụ đang chạy"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Còn <xliff:g id="TIME">%1$s</xliff:g> nữa là sạc đầy"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> nữa là sạc đầy"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Thời lượng pin bị hạn chế tạm thời"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Đang tối ưu hóa để cải thiện độ bền của pin"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Không xác định"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Đang sạc"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Đang sạc nhanh"</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index ca2ad87fb864..c9ecab19bfaf 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"已启用。点按即可切换。"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"应用待机状态:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"媒体转码设置"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"停用转码功能"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"覆盖转码默认设置"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"启用转码"</string> + <string name="transcode_default" msgid="3784803084573509491">"假设应用支持现代格式"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"为应用启用转码功能"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"正在运行的服务"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"查看和控制当前正在运行的服务"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"还剩 <xliff:g id="TIME">%1$s</xliff:g>充满电"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>后充满电"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 暂时限用电池"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - 正在针对电池状况进行优化"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"正在充电"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"正在快速充电"</string> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index 16ca19d313c1..3bbfa21220de 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"已啟用。輕按即可切換。"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"備用應用程式狀態:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"媒體轉碼設定"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"停用轉碼功能"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"覆寫轉碼預設設定"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"啟用轉碼功能"</string> + <string name="transcode_default" msgid="3784803084573509491">"假設應用程式支援新型格式"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"為應用程式啟用轉碼功能"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"執行中的服務"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"查看並控制目前正在執行中的服務"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"還需 <xliff:g id="TIME">%1$s</xliff:g>才能充滿電"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 還需 <xliff:g id="TIME">%2$s</xliff:g>才能充滿電"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 暫時限制電池充電"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - 正在優化電池狀態"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"正在快速充電"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index 810119b97777..b0dbb5fdac66 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"已啟用。輕觸即可切換。"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"應用程式待命狀態:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"媒體轉碼功能設定"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"停用轉碼功能"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"覆寫轉碼預設設定"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"啟用轉碼"</string> + <string name="transcode_default" msgid="3784803084573509491">"假設應用程式支援新格式"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"替應用程式啟用轉碼功能"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"正在運作的服務"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"查看並管理目前正在執行的服務"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g>後充飽電"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽電"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 暫時限制電池用量"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - 針對電池狀態進行最佳化調整"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"快速充電中"</string> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index 23beeb1aee82..8f7c2ac100bc 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Kuyasebenza. Thepha ukuze ushintshe."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Isimo sokulinda kohlelo lokusebenza:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Amasethingi wemidiya yokudlulisela ikhodi"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Khubaza ukudlulisela ikhodi"</string> + <string name="transcode_user_control" msgid="6176368544817731314">"Khipha okuzenzakalelayo kokudlulisela ikhodi"</string> + <string name="transcode_enable_all" msgid="2411165920039166710">"Nika amandla ukudlulisela ikhodi"</string> + <string name="transcode_default" msgid="3784803084573509491">"Kuthathe njengokungathi izinhlelo zokusebenza zisekela amafomethi esimanje"</string> <string name="transcode_skip_apps" msgid="8249721984597390142">"Nika amandla ukudlulisela ikhodi kwezinhlelo zokusebenza"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Amasevisi asebenzayo"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Buka futhi ulawule amasevisi asebenzayo okwamanje"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> esele ize ishaje"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ize igcwale"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ibhethri ikhawulelwe okwesikhashana"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ilungiselela impilo yebhethri"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Akwaziwa"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Iyashaja"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ishaja ngokushesha"</string> diff --git a/packages/SettingsLib/res/values/attrs.xml b/packages/SettingsLib/res/values/attrs.xml index 9aed54e12a2d..1e6cb33433c7 100644 --- a/packages/SettingsLib/res/values/attrs.xml +++ b/packages/SettingsLib/res/values/attrs.xml @@ -46,8 +46,6 @@ <attr name="wifi_signal" format="reference" /> <attr name="wifi_friction" format="reference" /> - <attr name="footerPreferenceStyle" format="reference" /> - <!-- Workaround for b/74248169. These are duplicates of attrs in AndroidX preferences. --> <attr name="preferenceStyle" format="reference" /> <attr name="switchPreferenceStyle" format="reference" /> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 22213cba217d..4e9721218a02 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -1004,9 +1004,6 @@ <!-- Settings item title to select the default behavior for transcoding if an encodig is not supported by an app. [CHAR LIMIT=85] --> <string name="transcode_default">Assume apps support modern formats</string> - <!-- Settings category title for selecting apps to be enabled for transcoding. [CHAR LIMIT=85] --> - <string name="transcode_skip_apps">Enable transcoding for apps</string> - <!-- Services settings screen, setting option name for the user to go to the screen to view running services --> <string name="runningservices_settings_title">Running services</string> <!-- Services settings screen, setting option summary for the user to go to the screen to view running services --> diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java index 41d6afc9c234..f21c3598a23d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java @@ -38,6 +38,7 @@ import android.graphics.drawable.Drawable; import android.media.MediaRoute2Info; import android.media.MediaRouter2Manager; import android.text.TextUtils; +import android.util.Log; import androidx.annotation.IntDef; import androidx.annotation.VisibleForTesting; @@ -46,6 +47,7 @@ import com.android.settingslib.R; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; import java.util.List; /** @@ -199,6 +201,10 @@ public abstract class MediaDevice implements Comparable<MediaDevice> { */ public void requestSetVolume(int volume) { + if (mRouteInfo == null) { + Log.w(TAG, "Unable to set volume. RouteInfo is empty"); + return; + } mRouterManager.setRouteVolume(mRouteInfo, volume); } @@ -208,6 +214,10 @@ public abstract class MediaDevice implements Comparable<MediaDevice> { * @return max volume. */ public int getMaxVolume() { + if (mRouteInfo == null) { + Log.w(TAG, "Unable to get max volume. RouteInfo is empty"); + return 0; + } return mRouteInfo.getVolumeMax(); } @@ -217,6 +227,10 @@ public abstract class MediaDevice implements Comparable<MediaDevice> { * @return current volume. */ public int getCurrentVolume() { + if (mRouteInfo == null) { + Log.w(TAG, "Unable to get current volume. RouteInfo is empty"); + return 0; + } return mRouteInfo.getVolume(); } @@ -226,6 +240,10 @@ public abstract class MediaDevice implements Comparable<MediaDevice> { * @return package name. */ public String getClientPackageName() { + if (mRouteInfo == null) { + Log.w(TAG, "Unable to get client package name. RouteInfo is empty"); + return null; + } return mRouteInfo.getClientPackageName(); } @@ -244,6 +262,10 @@ public abstract class MediaDevice implements Comparable<MediaDevice> { * @return result of transfer media */ public boolean connect() { + if (mRouteInfo == null) { + Log.w(TAG, "Unable to connect. RouteInfo is empty"); + return false; + } setConnectedRecord(); mRouterManager.selectRoute(mPackageName, mRouteInfo); return true; @@ -358,6 +380,10 @@ public abstract class MediaDevice implements Comparable<MediaDevice> { * Gets the supported features of the route. */ public List<String> getFeatures() { + if (mRouteInfo == null) { + Log.w(TAG, "Unable to get features. RouteInfo is empty"); + return new ArrayList<>(); + } return mRouteInfo.getFeatures(); } diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java new file mode 100644 index 000000000000..56898605ec94 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.settingslib.mobile; + +import android.telephony.Annotation; +import android.telephony.TelephonyDisplayInfo; +import android.telephony.TelephonyManager; + +/** + * Holds the utility functions to create the RAT to MobileIconGroup mappings. + */ +public class MobileMappings { + + /** + * Generates the RAT key from the TelephonyDisplayInfo. + */ + public static String getIconKey(TelephonyDisplayInfo telephonyDisplayInfo) { + if (telephonyDisplayInfo.getOverrideNetworkType() + == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) { + return toIconKey(telephonyDisplayInfo.getNetworkType()); + } else { + return toDisplayIconKey(telephonyDisplayInfo.getOverrideNetworkType()); + } + } + + /** + * Converts the networkType into the RAT key. + */ + public static String toIconKey(@Annotation.NetworkType int networkType) { + return Integer.toString(networkType); + } + + /** + * Converts the displayNetworkType into the RAT key. + */ + public static String toDisplayIconKey(@Annotation.OverrideNetworkType int displayNetworkType) { + switch (displayNetworkType) { + case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA: + return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA"; + case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO: + return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA_Plus"; + case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA: + return toIconKey(TelephonyManager.NETWORK_TYPE_NR); + case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE: + return toIconKey(TelephonyManager.NETWORK_TYPE_NR) + "_Plus"; + default: + return "unsupported"; + } + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java new file mode 100644 index 000000000000..b8030f166436 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.settingslib.mobile; + +import android.os.Handler; +import android.os.Looper; +import android.telephony.PhoneStateListener; +import android.telephony.ServiceState; +import android.telephony.SignalStrength; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyDisplayInfo; +import android.telephony.TelephonyManager; +import android.util.Log; + +/** + * Tracks the mobile signal status for the SysUI and Settings. + * + * This class is not threadsafe. All the mobile statuses monitored by this class is stored in + * MobileStatus. Whoever uses this class should only rely on the MobileStatusTracker#Callback + * to get the latest mobile statuses. Do not get mobile statues directly from + * MobileStatusTracker#MobileStatus. + */ +public class MobileStatusTracker { + private static final String TAG = "MobileStatusTracker"; + private final TelephonyManager mPhone; + private final SubscriptionInfo mSubscriptionInfo; + private final Callback mCallback; + private final MobileStatus mMobileStatus; + private final PhoneStateListener mPhoneStateListener; + private final SubscriptionDefaults mDefaults; + private final Handler mReceiverHandler; + + /** + * MobileStatusTracker constructors + * + * @param phone The TelephonyManager which corresponds to the subscription being monitored. + * @param receiverLooper The Looper on which the callback will be invoked. + * @param info The subscription being monitored. + * @param defaults The wrapper of the SubscriptionManager. + * @param callback The callback to notify any changes of the mobile status, users should only + * use this callback to get the latest mobile status. + */ + public MobileStatusTracker(TelephonyManager phone, Looper receiverLooper, + SubscriptionInfo info, SubscriptionDefaults defaults, Callback callback) { + mPhone = phone; + mReceiverHandler = new Handler(receiverLooper); + mPhoneStateListener = new MobilePhoneStateListener(); + mSubscriptionInfo = info; + mDefaults = defaults; + mCallback = callback; + mMobileStatus = new MobileStatus(); + updateDataSim(); + mReceiverHandler.post(() -> mCallback.onMobileStatusChanged( + /* updateTelephony= */false, new MobileStatus(mMobileStatus))); + } + + public PhoneStateListener getPhoneStateListener() { + return mPhoneStateListener; + } + + /** + * Config the MobileStatusTracker to start or stop monitoring platform signals. + */ + public void setListening(boolean listening) { + if (listening) { + mPhone.registerPhoneStateListener(mReceiverHandler::post, mPhoneStateListener); + } else { + mPhone.unregisterPhoneStateListener(mPhoneStateListener); + } + } + + private void updateDataSim() { + int activeDataSubId = mDefaults.getActiveDataSubId(); + if (SubscriptionManager.isValidSubscriptionId(activeDataSubId)) { + mMobileStatus.dataSim = activeDataSubId == mSubscriptionInfo.getSubscriptionId(); + } else { + // There doesn't seem to be a data sim selected, however if + // there isn't a MobileSignalController with dataSim set, then + // QS won't get any callbacks and will be blank. Instead + // lets just assume we are the data sim (which will basically + // show one at random) in QS until one is selected. The user + // should pick one soon after, so we shouldn't be in this state + // for long. + mMobileStatus.dataSim = true; + } + } + + private void setActivity(int activity) { + mMobileStatus.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT + || activity == TelephonyManager.DATA_ACTIVITY_IN; + mMobileStatus.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT + || activity == TelephonyManager.DATA_ACTIVITY_OUT; + } + + private class MobilePhoneStateListener extends PhoneStateListener implements + PhoneStateListener.ServiceStateChangedListener, + PhoneStateListener.SignalStrengthsChangedListener, + PhoneStateListener.CallStateChangedListener, + PhoneStateListener.DataConnectionStateChangedListener, + PhoneStateListener.DataActivityListener, + PhoneStateListener.CarrierNetworkChangeListener, + PhoneStateListener.ActiveDataSubscriptionIdChangedListener, + PhoneStateListener.DisplayInfoChangedListener{ + + @Override + public void onSignalStrengthsChanged(SignalStrength signalStrength) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength + + ((signalStrength == null) ? "" + : (" level=" + signalStrength.getLevel()))); + } + mMobileStatus.signalStrength = signalStrength; + mCallback.onMobileStatusChanged( + /* updateTelephony= */true, new MobileStatus(mMobileStatus)); + } + + @Override + public void onServiceStateChanged(ServiceState state) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "onServiceStateChanged voiceState=" + + (state == null ? "" : state.getState()) + + " dataState=" + (state == null ? "" : state.getDataRegistrationState())); + } + mMobileStatus.serviceState = state; + mCallback.onMobileStatusChanged( + /* updateTelephony= */true, new MobileStatus(mMobileStatus)); + } + + @Override + public void onDataConnectionStateChanged(int state, int networkType) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "onDataConnectionStateChanged: state=" + state + + " type=" + networkType); + } + mMobileStatus.dataState = state; + mCallback.onMobileStatusChanged( + /* updateTelephony= */true, new MobileStatus(mMobileStatus)); + } + + @Override + public void onDataActivity(int direction) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "onDataActivity: direction=" + direction); + } + setActivity(direction); + mCallback.onMobileStatusChanged( + /* updateTelephony= */false, new MobileStatus(mMobileStatus)); + } + + @Override + public void onCarrierNetworkChange(boolean active) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "onCarrierNetworkChange: active=" + active); + } + mMobileStatus.carrierNetworkChangeMode = active; + mCallback.onMobileStatusChanged( + /* updateTelephony= */true, new MobileStatus(mMobileStatus)); + } + + @Override + public void onActiveDataSubscriptionIdChanged(int subId) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "onActiveDataSubscriptionIdChanged: subId=" + subId); + } + updateDataSim(); + mCallback.onMobileStatusChanged( + /* updateTelephony= */true, new MobileStatus(mMobileStatus)); + } + + @Override + public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "onDisplayInfoChanged: telephonyDisplayInfo=" + telephonyDisplayInfo); + } + mMobileStatus.telephonyDisplayInfo = telephonyDisplayInfo; + mCallback.onMobileStatusChanged( + /* updateTelephony= */ true, new MobileStatus(mMobileStatus)); + } + } + + /** + * Wrapper class of the SubscriptionManager, for mock testing purpose + */ + public static class SubscriptionDefaults { + public int getDefaultVoiceSubId() { + return SubscriptionManager.getDefaultVoiceSubscriptionId(); + } + + public int getDefaultDataSubId() { + return SubscriptionManager.getDefaultDataSubscriptionId(); + } + + public int getActiveDataSubId() { + return SubscriptionManager.getActiveDataSubscriptionId(); + } + } + + /** + * Wrapper class which contains all the mobile status tracked by MobileStatusTracker. + */ + public static class MobileStatus { + public boolean activityIn; + public boolean activityOut; + public boolean dataSim; + public boolean carrierNetworkChangeMode; + public int dataState = TelephonyManager.DATA_DISCONNECTED; + public ServiceState serviceState; + public SignalStrength signalStrength; + public TelephonyDisplayInfo telephonyDisplayInfo = + new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN, + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE); + + /** + * Empty constructor + */ + public MobileStatus() { } + + /** + * Copy constructors + * + * @param status Source MobileStatus + */ + public MobileStatus(MobileStatus status) { + copyFrom(status); + } + + protected void copyFrom(MobileStatus status) { + activityIn = status.activityIn; + activityOut = status.activityOut; + dataSim = status.dataSim; + carrierNetworkChangeMode = status.carrierNetworkChangeMode; + dataState = status.dataState; + // We don't do deep copy for the below members since they may be Mockito instances. + serviceState = status.serviceState; + signalStrength = status.signalStrength; + telephonyDisplayInfo = status.telephonyDisplayInfo; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + return builder.append("[activityIn=").append(activityIn).append(',') + .append("activityOut=").append(activityOut).append(',') + .append("dataSim=").append(dataSim).append(',') + .append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode).append(',') + .append("dataState=").append(dataState).append(',') + .append("serviceState=").append(serviceState == null ? "" + : serviceState.toString()).append(',') + .append("signalStrength=").append(signalStrength == null ? "" + : signalStrength.toString()).append(',') + .append("telephonyDisplayInfo=").append(telephonyDisplayInfo == null ? "" + : telephonyDisplayInfo.toString()).append(']').toString(); + } + } + + /** + * Callback for notifying any changes of the mobile status. + * + * This callback will always be invoked on the receiverLooper which must be specified when + * MobileStatusTracker is constructed. + */ + public interface Callback { + /** + * Notify the mobile status has been updated. + * + * @param updateTelephony Whether needs to update other Telephony related parameters, this + * is only used by SysUI. + * @param mobileStatus Holds the latest mobile statuses + */ + void onMobileStatusChanged(boolean updateTelephony, MobileStatus mobileStatus); + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/emergencynumber/EmergencyNumberUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/emergencynumber/EmergencyNumberUtilsTest.java index 140363127dff..99d2ff7f322f 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/emergencynumber/EmergencyNumberUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/emergencynumber/EmergencyNumberUtilsTest.java @@ -113,12 +113,13 @@ public class EmergencyNumberUtilsTest { private void addEmergencyNumberToTelephony() { final int subId = SubscriptionManager.getDefaultSubscriptionId(); EmergencyNumber emergencyNumber = mock(EmergencyNumber.class); + when(emergencyNumber.isInEmergencyServiceCategories(EMERGENCY_SERVICE_CATEGORY_POLICE)) + .thenReturn(true); Map<Integer, List<EmergencyNumber>> numbers = new ArrayMap<>(); List<EmergencyNumber> numbersForSubId = new ArrayList<>(); numbersForSubId.add(emergencyNumber); numbers.put(subId, numbersForSubId); - when(mTelephonyManager.getEmergencyNumberList( - EMERGENCY_SERVICE_CATEGORY_POLICE)).thenReturn(numbers); + when(mTelephonyManager.getEmergencyNumberList()).thenReturn(numbers); when(emergencyNumber.getNumber()).thenReturn(TELEPHONY_EMERGENCY_NUMBER); } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java index 47d4beb752c5..6f7f73a3e79b 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java @@ -465,4 +465,12 @@ public class MediaDeviceTest { assertThat(mInfoMediaDevice1.getState()).isEqualTo( LocalMediaManager.MediaDeviceState.STATE_CONNECTING_FAILED); } + + @Test + public void getFeatures_noRouteInfo_returnEmptyList() { + mBluetoothMediaDevice1 = new BluetoothMediaDevice(mContext, mCachedDevice1, + mMediaRouter2Manager, null /* MediaRoute2Info */, TEST_PACKAGE_NAME); + + assertThat(mBluetoothMediaDevice1.getFeatures().size()).isEqualTo(0); + } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index a61e3cd5f4ab..c9e3b6f63135 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -3342,7 +3342,7 @@ public class SettingsProvider extends ContentProvider { } private final class UpgradeController { - private static final int SETTINGS_VERSION = 195; + private static final int SETTINGS_VERSION = 196; private final int mUserId; @@ -4777,6 +4777,15 @@ public class SettingsProvider extends ContentProvider { currentVersion = 195; } + if (currentVersion == 195) { + // Version 195: delete obsolete manged services settings + getSecureSettingsLocked(userId).deleteSettingLocked( + Secure.ENABLED_NOTIFICATION_ASSISTANT); + getSecureSettingsLocked(userId).deleteSettingLocked( + Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES); + currentVersion = 196; + } + // vXXX: Add new settings above this point. if (currentVersion != newVersion) { diff --git a/packages/SharedStorageBackup/OWNERS b/packages/SharedStorageBackup/OWNERS new file mode 100644 index 000000000000..d99779e3d9da --- /dev/null +++ b/packages/SharedStorageBackup/OWNERS @@ -0,0 +1 @@ +include /services/backup/OWNERS diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 141b8cbe8022..cb1faf5e5163 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -181,6 +181,8 @@ <!-- Permissions needed to test system only camera devices --> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.SYSTEM_CAMERA" /> + <!-- Permissions needed to test onCameraOpened/Closed callbacks --> + <uses-permission android:name="android.permission.CAMERA_OPEN_CLOSE_LISTENER" /> <!-- Permissions needed for CTS camera test: RecordingTest.java when assuming shell id --> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- Permission needed to enable/disable Bluetooth/Wifi --> @@ -281,6 +283,9 @@ <uses-permission android:name="android.permission.MANAGE_NOTIFICATIONS"/> <uses-permission android:name="android.permission.ACCESS_LOCUS_ID_USAGE_STATS"/> + <!-- Permission needed for CTS test - MusicRecognitionManagerTest --> + <uses-permission android:name="android.permission.MANAGE_MUSIC_RECOGNITION" /> + <!-- Permissions required to test ambient display. --> <uses-permission android:name="android.permission.READ_DREAM_STATE"/> <uses-permission android:name="android.permission.WRITE_DREAM_STATE"/> diff --git a/packages/Shell/OWNERS b/packages/Shell/OWNERS index 6ba1fcb058b1..2d7a3e68f86a 100644 --- a/packages/Shell/OWNERS +++ b/packages/Shell/OWNERS @@ -1,6 +1,6 @@ set noparent -jsharkey@android.com +jsharkey@google.com felipeal@google.com nandana@google.com svetoslavganov@google.com diff --git a/packages/StatementService/Android.bp b/packages/StatementService/Android.bp index ae37efc9a545..2664a0316f5c 100644 --- a/packages/StatementService/Android.bp +++ b/packages/StatementService/Android.bp @@ -21,6 +21,7 @@ android_app { platform_apis: true, privileged: true, libs: ["org.apache.http.legacy"], + uses_libs: ["org.apache.http.legacy"], static_libs: [ "libprotobuf-java-nano", "volley", diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 2da958f6b8b9..285c4a172e68 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -576,6 +576,7 @@ android:launchMode="singleInstance"> <intent-filter> <action android:name="android.intent.action.MAIN"/> + <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS index f884270eaba8..3bda7106defa 100644 --- a/packages/SystemUI/OWNERS +++ b/packages/SystemUI/OWNERS @@ -1,6 +1,6 @@ set noparent -dsandler@android.com +dsandler@google.com aaliomer@google.com adamcohen@google.com diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java index 6e86f268a725..4fc197340e92 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java @@ -60,8 +60,8 @@ public interface FalsingManager { * Returns true if the last two gestures do not look like a double tap. * * Only works on data that has already been reported to the FalsingManager. Be sure that - * {@link #onTouchEvent(MotionEvent, int, int)} has already been called for all of the - * taps you want considered. + * {@link com.android.systemui.classifier.FalsingCollector#onTouchEvent(MotionEvent)} + * has already been called for all of the taps you want considered. * * This looks at the last two gestures on the screen, ensuring that they meet the following * criteria: @@ -85,8 +85,6 @@ public interface FalsingManager { boolean isReportingEnabled(); - void onTouchEvent(MotionEvent ev, int width, int height); - /** From com.android.systemui.Dumpable. */ void dump(FileDescriptor fd, PrintWriter pw, String[] args); diff --git a/packages/SystemUI/res-keyguard/values-af/strings.xml b/packages/SystemUI/res-keyguard/values-af/strings.xml index 276fa23e8578..6f23f8c0b2b8 100644 --- a/packages/SystemUI/res-keyguard/values-af/strings.xml +++ b/packages/SystemUI/res-keyguard/values-af/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans vinnig"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans stadig"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimeer tans vir batterygesondheid"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Koppel jou laaier."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Druk Kieslys om te ontsluit."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk is gesluit"</string> diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml index ae5d1f675c52..62f955438e44 100644 --- a/packages/SystemUI/res-keyguard/values-am/strings.xml +++ b/packages/SystemUI/res-keyguard/values-am/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ኃይል በመሙላት ላይ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በፍጥነት ኃይልን በመሙላት ላይ"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ለባትሪ ጤና ማመቻቸት"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"ኃይል መሙያዎን ያያይዙ።"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ለመክፈት ምናሌ ተጫን።"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"አውታረ መረብ ተቆልፏል"</string> diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml index fb03fe340c3a..459d162c65db 100644 --- a/packages/SystemUI/res-keyguard/values-ar/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن سريعًا"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن ببطء"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • التحسين لسلامة البطارية"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"توصيل جهاز الشحن."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"اضغط على \"القائمة\" لإلغاء التأمين."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"الشبكة مؤمّنة"</string> diff --git a/packages/SystemUI/res-keyguard/values-as/strings.xml b/packages/SystemUI/res-keyguard/values-as/strings.xml index 8e8b13d0a160..84a8afa04286 100644 --- a/packages/SystemUI/res-keyguard/values-as/strings.xml +++ b/packages/SystemUI/res-keyguard/values-as/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চ্চার্জ কৰি থকা হৈছে"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্ৰুত গতিৰে চ্চাৰ্জ কৰি থকা হৈছে"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • লাহে লাহে চ্চাৰ্জ কৰি থকা হৈছে"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • বেটাৰীৰ অৱস্থা অপ্টিমাইজ কৰি থকা হৈছে"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"আপোনাৰ চ্চার্জাৰ সংযোগ কৰক।"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"আনলক কৰিবলৈ মেনু টিপক।"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটৱর্ক লক কৰা অৱস্থাত আছে"</string> diff --git a/packages/SystemUI/res-keyguard/values-az/strings.xml b/packages/SystemUI/res-keyguard/values-az/strings.xml index f9bff73a671f..e1846796dc2f 100644 --- a/packages/SystemUI/res-keyguard/values-az/strings.xml +++ b/packages/SystemUI/res-keyguard/values-az/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Enerji yığır"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sürətlə enerji yığır"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş enerji yığır"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Enerjiyə qənaət üçün optimallaşdırma"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Adapteri qoşun."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Kilidi açmaq üçün Menyu düyməsinə basın."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Şəbəkə kilidlidir"</string> diff --git a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml index 3434ac67bb73..346874060759 100644 --- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Puni se"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo se puni"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo se puni"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizuje se radi dobrog stanja baterije"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite punjač."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite Meni da biste otključali."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string> diff --git a/packages/SystemUI/res-keyguard/values-be/strings.xml b/packages/SystemUI/res-keyguard/values-be/strings.xml index 07d682f69f56..4f8ce16e9106 100644 --- a/packages/SystemUI/res-keyguard/values-be/strings.xml +++ b/packages/SystemUI/res-keyguard/values-be/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе зарадка"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе хуткая зарадка"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе павольная зарадка"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Аптымізацыя стану акумулятара"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Падключыце зарадную прыладу."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Націсніце кнопку \"Меню\", каб разблакіраваць."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сетка заблакіравана"</string> diff --git a/packages/SystemUI/res-keyguard/values-bg/strings.xml b/packages/SystemUI/res-keyguard/values-bg/strings.xml index 3890c11f9450..0911efade706 100644 --- a/packages/SystemUI/res-keyguard/values-bg/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bg/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бързо"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бавно"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Оптимизиране за състоянието на батерията"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Свържете зарядното си устройство."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Натиснете „Меню“, за да отключите."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заключена"</string> diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml index f9163747aff7..0c878b6e0175 100644 --- a/packages/SystemUI/res-keyguard/values-bn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চার্জ হচ্ছে"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্রুত চার্জ হচ্ছে"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ধীরে চার্জ হচ্ছে"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ব্যাটারির চার্জ অপটিমাইজ করা হচ্ছে"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"আপনার চার্জার সংযুক্ত করুন।"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"আনলক করতে মেনুতে টিপুন।"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটওয়ার্ক লক করা আছে"</string> diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml index 59a881db8e33..83ad38c74598 100644 --- a/packages/SystemUI/res-keyguard/values-bs/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo punjenje"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo punjenje"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimiziranje radi očuvanja baterije"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite punjač."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite meni da otključate."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string> diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml index 82d63c157441..421ddb6d31e6 100644 --- a/packages/SystemUI/res-keyguard/values-ca/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant ràpidament"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant lentament"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està optimitzant per mantenir el bon estat de la bateria"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Connecta el carregador."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Prem Menú per desbloquejar."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"La xarxa està bloquejada"</string> diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml index a4e653f19678..855d3f0eb968 100644 --- a/packages/SystemUI/res-keyguard/values-cs/strings.xml +++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjení"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Rychlé nabíjení"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pomalé nabíjení"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimalizace pro výdrž baterie"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Připojte dobíjecí zařízení."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Klávesy odemknete stisknutím tlačítka nabídky."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Síť je blokována"</string> diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml index 604852cfeb45..b5955c7d61e1 100644 --- a/packages/SystemUI/res-keyguard/values-da/strings.xml +++ b/packages/SystemUI/res-keyguard/values-da/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader hurtigt"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader langsomt"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimerer batteritilstanden"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Tilslut din oplader."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tryk på menuen for at låse op."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netværket er låst"</string> diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml index 0e2ea136f263..d700df382ea9 100644 --- a/packages/SystemUI/res-keyguard/values-de/strings.xml +++ b/packages/SystemUI/res-keyguard/values-de/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird geladen"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird schnell geladen"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird langsam geladen"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimierung des Akkuzustands"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Ladegerät anschließen."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Zum Entsperren die Menütaste drücken."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netzwerk gesperrt"</string> diff --git a/packages/SystemUI/res-keyguard/values-el/strings.xml b/packages/SystemUI/res-keyguard/values-el/strings.xml index 90e255031dd1..b3056981caaa 100644 --- a/packages/SystemUI/res-keyguard/values-el/strings.xml +++ b/packages/SystemUI/res-keyguard/values-el/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Φόρτιση"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Γρήγορη φόρτιση"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Αργή φόρτιση"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Βελτιστοποίηση για τη διατήρηση της καλής κατάστασης της μπαταρίας"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Συνδέστε τον φορτιστή."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Πατήστε \"Μενού\" για ξεκλείδωμα."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Κλειδωμένο δίκτυο"</string> diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml index 7b0c638dcdf3..54c1a2b039a3 100644 --- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimising for battery health"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string> diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml index 2ef720e44735..d8591e260d0b 100644 --- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimising for battery health"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string> diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml index 7b0c638dcdf3..54c1a2b039a3 100644 --- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimising for battery health"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string> diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml index 7b0c638dcdf3..54c1a2b039a3 100644 --- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimising for battery health"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string> diff --git a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml index 471ef8ba83d9..30f47d21b178 100644 --- a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizing for battery health"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string> diff --git a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml index a5750b550295..4ea99ccdd419 100644 --- a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml +++ b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se está optimizando el estado de la batería"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecta tu cargador."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Presiona Menú para desbloquear."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string> diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml index 69488da11576..b7384c5e3893 100644 --- a/packages/SystemUI/res-keyguard/values-es/strings.xml +++ b/packages/SystemUI/res-keyguard/values-es/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizando para preservar el estado de la batería"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecta el cargador."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pulsa el menú para desbloquear la pantalla."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string> diff --git a/packages/SystemUI/res-keyguard/values-et/strings.xml b/packages/SystemUI/res-keyguard/values-et/strings.xml index 948e134e68ec..a01d30db30db 100644 --- a/packages/SystemUI/res-keyguard/values-et/strings.xml +++ b/packages/SystemUI/res-keyguard/values-et/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laadimine"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kiirlaadimine"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Aeglane laadimine"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimeerimine aku seisukorra põhjal"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Ühendage laadija."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Vajutage avamiseks menüüklahvi."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Võrk on lukus"</string> diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml index b1aa206364a4..ce8ef202a038 100644 --- a/packages/SystemUI/res-keyguard/values-eu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzen"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bizkor kargatzen"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mantso kargatzen"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizatzen bateria egoera onean mantentzeko"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Konektatu kargagailua."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Desblokeatzeko, sakatu Menua."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sarea blokeatuta dago"</string> diff --git a/packages/SystemUI/res-keyguard/values-fa/strings.xml b/packages/SystemUI/res-keyguard/values-fa/strings.xml index 8fecdd3ee980..61e2e1fc78db 100644 --- a/packages/SystemUI/res-keyguard/values-fa/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fa/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ شدن"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ سریع"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آهستهآهسته شارژ میشود"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • بهینهسازی برای سلامت باتری"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"شارژر را وصل کنید."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"برای باز کردن قفل روی «منو» فشار دهید."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"شبکه قفل شد"</string> diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml index c47de5dc8cf7..021de770f2c1 100644 --- a/packages/SystemUI/res-keyguard/values-fi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan nopeasti"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan hitaasti"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Akun kunnon optimointi"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Kytke laturi."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Poista lukitus painamalla Valikkoa."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Verkko lukittu"</string> diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml index b330452f5bbe..d1a1582cbcb5 100644 --- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"En recharge : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"En recharge rapide : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"En recharge lente : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimisation en fonction de la santé de la pile"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Branchez votre chargeur."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur la touche Menu pour déverrouiller l\'appareil."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string> diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml index 0c13c0f0cb0d..ba35acd34d8c 100644 --- a/packages/SystemUI/res-keyguard/values-fr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge…"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge rapide…"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge lente…"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimisation pour préserver la batterie"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Branchez votre chargeur."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur \"Menu\" pour déverrouiller le clavier."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string> diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml index 601b2e23aba1..01a0fac58016 100644 --- a/packages/SystemUI/res-keyguard/values-gl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rapidamente"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizando para manter a batería en bo estado"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecta o cargador."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Preme Menú para desbloquear."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada pola rede"</string> diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml index 296124fc743d..8ec7ba595837 100644 --- a/packages/SystemUI/res-keyguard/values-gu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ચાર્જિંગ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ઝડપથી ચાર્જિંગ"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ધીમેથી ચાર્જિંગ"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • બૅટરીની ક્ષમતા વધારવા ઑપ્ટિમાઇઝ કરી રહ્યાં છીએ"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"તમારું ચાર્જર કનેક્ટ કરો."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"અનલૉક કરવા માટે મેનૂ દબાવો."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"નેટવર્ક લૉક થયું"</string> diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml index c1c9dd57a64f..5869078dc598 100644 --- a/packages/SystemUI/res-keyguard/values-hi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज हो रहा है"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • तेज़ चार्ज हो रहा है"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • धीरे चार्ज हो रहा है"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • बैटरी की परफ़ॉर्मेंस बेहतर करने के लिए, ऑप्टिमाइज़ किया जा रहा है"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"अपना चार्जर कनेक्ट करें."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"लॉक खोलने के लिए मेन्यू दबाएं."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक किया हुआ है"</string> diff --git a/packages/SystemUI/res-keyguard/values-hr/strings.xml b/packages/SystemUI/res-keyguard/values-hr/strings.xml index 1b51b33c9843..7e0697337481 100644 --- a/packages/SystemUI/res-keyguard/values-hr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hr/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • punjenje"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • brzo punjenje"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • sporo punjenje"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimiziranje radi zdravlja baterije"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite punjač."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite Izbornik da biste otključali."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string> diff --git a/packages/SystemUI/res-keyguard/values-hu/strings.xml b/packages/SystemUI/res-keyguard/values-hu/strings.xml index 4dcb22971979..e6c10d821cdb 100644 --- a/packages/SystemUI/res-keyguard/values-hu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hu/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Töltés"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Gyors töltés"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lassú töltés"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Az akkumulátor élettartamának optimalizálása…"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Csatlakoztassa a töltőt."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"A feloldáshoz nyomja meg a Menü gombot."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Hálózat zárolva"</string> diff --git a/packages/SystemUI/res-keyguard/values-hy/strings.xml b/packages/SystemUI/res-keyguard/values-hy/strings.xml index 354d93208f15..c8ed16d10327 100644 --- a/packages/SystemUI/res-keyguard/values-hy/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hy/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Լիցքավորում"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Արագ լիցքավորում"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Դանդաղ լիցքավորում"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Օպտիմալացվում է մարտկոցի աշխատանքային հզորության համար"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Միացրեք լիցքավորիչը:"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ապակողպելու համար սեղմեք Ընտրացանկը:"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Ցանցը կողպված է"</string> diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml index d43823cea147..696f215c751e 100644 --- a/packages/SystemUI/res-keyguard/values-in/strings.xml +++ b/packages/SystemUI/res-keyguard/values-in/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan cepat"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan lambat"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengoptimalkan untuk kesehatan baterai"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Hubungkan pengisi daya."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Jaringan terkunci"</string> diff --git a/packages/SystemUI/res-keyguard/values-is/strings.xml b/packages/SystemUI/res-keyguard/values-is/strings.xml index 233402b33f26..3f3bec9b8c8c 100644 --- a/packages/SystemUI/res-keyguard/values-is/strings.xml +++ b/packages/SystemUI/res-keyguard/values-is/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Í hleðslu"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hröð hleðsla"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hæg hleðsla"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Fínstillir til að bæta rafhlöðuendingu"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Tengdu hleðslutækið."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ýttu á valmyndarhnappinn til að taka úr lás."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Net læst"</string> diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml index 87fd81cb1581..47d17ce57892 100644 --- a/packages/SystemUI/res-keyguard/values-it/strings.xml +++ b/packages/SystemUI/res-keyguard/values-it/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • In carica"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica veloce"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica lenta"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Batteria momentaneamente limitata"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • È in corso l\'ottimizzazione per l\'integrità della batteria"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Collega il caricabatterie."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Premi Menu per sbloccare."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rete bloccata"</string> diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml index 6af70b4cebf3..8780dc5e3c01 100644 --- a/packages/SystemUI/res-keyguard/values-iw/strings.xml +++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה מהירה"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה איטית"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • מופעלת אופטימיזציה לשמירה על תקינות הסוללה"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"חבר את המטען."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"לחץ על \'תפריט\' כדי לבטל את הנעילה."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"הרשת נעולה"</string> diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml index ab5a13c16bad..b4aea6182e65 100644 --- a/packages/SystemUI/res-keyguard/values-ja/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 急速充電中"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 低速充電中"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 電池の状態を最適化"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"充電してください。"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"メニューからロックを解除できます。"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ネットワークがロックされました"</string> diff --git a/packages/SystemUI/res-keyguard/values-ka/strings.xml b/packages/SystemUI/res-keyguard/values-ka/strings.xml index b10ab615abd0..7e1e59b9f445 100644 --- a/packages/SystemUI/res-keyguard/values-ka/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ka/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • იტენება"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • სწრაფად იტენება"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ნელა იტენება"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ბატარეა დროებით შეზღუდულია"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ოპტიმიზაცია ბატარეის გამართულობისთვის"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"შეაერთეთ დამტენი."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"განსაბლოკად დააჭირეთ მენიუს."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ქსელი ჩაკეტილია"</string> diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml index c415bbbe1a72..b20cb05ea86f 100644 --- a/packages/SystemUI/res-keyguard/values-kk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядталуда"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жылдам зарядталуда"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Баяу зарядталуда"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареяның жұмыс істеу қабілеті оңтайландырылуда"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Зарядтағышты қосыңыз."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ашу үшін \"Мәзір\" пернесін басыңыз."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Желі құлыптаулы"</string> diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml index 1a278e8262c8..fb38bfd88bd4 100644 --- a/packages/SystemUI/res-keyguard/values-km/strings.xml +++ b/packages/SystemUI/res-keyguard/values-km/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្ម"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្មយ៉ាងឆាប់រហ័ស"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្មយឺត"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងបង្កើនប្រសិទ្ធភាពគុណភាពថ្ម"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"សូមសាកថ្មរបស់អ្នក។"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ចុចម៉ឺនុយ ដើម្បីដោះសោ។"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"បណ្ដាញជាប់សោ"</string> diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml index 961fcec69853..a52712379776 100644 --- a/packages/SystemUI/res-keyguard/values-kn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್ಮಾಡಲಾಗುತ್ತಿದೆ"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಬ್ಯಾಟರಿಯ ಆರೋಗ್ಯಕ್ಕಾಗಿ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"ನಿಮ್ಮ ಚಾರ್ಜರ್ ಸಂಪರ್ಕಗೊಳಿಸಿ."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ಅನ್ಲಾಕ್ ಮಾಡಲು ಮೆನು ಒತ್ತಿರಿ."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ನೆಟ್ವರ್ಕ್ ಲಾಕ್ ಆಗಿದೆ"</string> diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml index 2f93af920e17..7149cdf787b2 100644 --- a/packages/SystemUI/res-keyguard/values-ko/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 충전 중"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 고속 충전 중"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 저속 충전 중"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 배터리 상태 최적화 중"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"충전기를 연결하세요."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"잠금 해제하려면 메뉴를 누르세요."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"네트워크 잠김"</string> diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml index 7e929199f1bc..5327c01e5471 100644 --- a/packages/SystemUI/res-keyguard/values-ky/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Кубатталууда"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Тез кубатталууда"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жай кубатталууда"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареянын кубатын үнөмдөө иштетилди"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Кубаттагычка туташтырыңыз."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Кулпуну ачуу үчүн Менюну басыңыз."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Тармак кулпуланган"</string> diff --git a/packages/SystemUI/res-keyguard/values-lo/strings.xml b/packages/SystemUI/res-keyguard/values-lo/strings.xml index b96a2bb4aa4c..0f662c3c7f38 100644 --- a/packages/SystemUI/res-keyguard/values-lo/strings.xml +++ b/packages/SystemUI/res-keyguard/values-lo/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບດ່ວນ"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບຊ້າ"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງເພີ່ມປະສິດທິພາບເພື່ອສຸຂະພາບແບັດເຕີຣີ"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"ເຊື່ອມຕໍ່ສາຍສາກຂອງທ່ານ."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ກົດ \"ເມນູ\" ເພື່ອປົດລັອກ."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ເຄືອຂ່າຍຖືກລັອກ"</string> diff --git a/packages/SystemUI/res-keyguard/values-lt/strings.xml b/packages/SystemUI/res-keyguard/values-lt/strings.xml index 773f7c42ebd1..cc8cdfd4ac1f 100644 --- a/packages/SystemUI/res-keyguard/values-lt/strings.xml +++ b/packages/SystemUI/res-keyguard/values-lt/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Įkraunama"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Greitai įkraunama"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lėtai įkraunama"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizuojama siekiant apsaugoti akumuliatorių"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Prijunkite kroviklį."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Paspauskite meniu, jei norite atrakinti."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tinklas užrakintas"</string> diff --git a/packages/SystemUI/res-keyguard/values-lv/strings.xml b/packages/SystemUI/res-keyguard/values-lv/strings.xml index 68bf4cde3086..d6fdfaf17e27 100644 --- a/packages/SystemUI/res-keyguard/values-lv/strings.xml +++ b/packages/SystemUI/res-keyguard/values-lv/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek uzlāde"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek ātrā uzlāde"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek lēnā uzlāde"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Akumulatora darbības optimizēšana"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Pievienojiet uzlādes ierīci."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Lai atbloķētu, nospiediet izvēlnes ikonu."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tīkls ir bloķēts."</string> diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml index e51f77488726..66744e797b9c 100644 --- a/packages/SystemUI/res-keyguard/values-mk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Се полни"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо полнење"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Бавно полнење"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Се оптимизира за состојба на батерија"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Поврзете го полначот."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Притиснете „Мени“ за отклучување."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заклучена"</string> diff --git a/packages/SystemUI/res-keyguard/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml index 4b4391482833..66d0ac756bf5 100644 --- a/packages/SystemUI/res-keyguard/values-ml/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ml/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ചാർജ് ചെയ്യുന്നു"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • വേഗത്തിൽ ചാർജ് ചെയ്യുന്നു"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ബാറ്ററി നില ഒപ്റ്റിമൈസ് ചെയ്യുന്നു"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"നിങ്ങളുടെ ചാർജർ കണക്റ്റുചെയ്യുക."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"അൺലോക്കുചെയ്യാൻ മെനു അമർത്തുക."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"നെറ്റ്വർക്ക് ലോക്കുചെയ്തു"</string> diff --git a/packages/SystemUI/res-keyguard/values-mn/strings.xml b/packages/SystemUI/res-keyguard/values-mn/strings.xml index 4667252546c5..2ff4a22d6737 100644 --- a/packages/SystemUI/res-keyguard/values-mn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mn/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Цэнэглэж байна"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Хурдан цэнэглэж байна"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Удаан цэнэглэж байна"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батарейн чанарыг оновчилж байна"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Цэнэглэгчээ холбоно уу."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Түгжээг тайлах бол цэсийг дарна уу."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сүлжээ түгжигдсэн"</string> diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml index bdd390475c4a..e2ffc6240c09 100644 --- a/packages/SystemUI/res-keyguard/values-mr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज होत आहे"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • वेगाने चार्ज होत आहे"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • सावकाश चार्ज होत आहे"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • बॅटरीची क्षमता वाढवण्यासाठी ऑप्टिमाइझ करत आहे"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"तुमचा चार्जर कनेक्ट करा."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"अनलॉक करण्यासाठी मेनू दाबा."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक केले"</string> diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml index a5179887ce5d..dcd460bf6c7a 100644 --- a/packages/SystemUI/res-keyguard/values-ms/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan cepat"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan perlahan"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengoptimuman untuk kesihatan bateri"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Sambungkan pengecas anda."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rangkaian dikunci"</string> diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml index 07f3d38aa8c8..bbeadd0cba13 100644 --- a/packages/SystemUI/res-keyguard/values-my/strings.xml +++ b/packages/SystemUI/res-keyguard/values-my/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အားသွင်းနေသည်"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အမြန်အားသွင်းနေသည်"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • နှေးကွေးစွာ အားသွင်းနေသည်"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ဘက်ထရီအခြေအနေကို အကောင်းဆုံးဖြစ်အောင် လုပ်နေသည်"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"အားသွင်းကိရိယာကို ချိတ်ဆက်ပါ။"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"မီနူးကို နှိပ်၍ လော့ခ်ဖွင့်ပါ။"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ကွန်ရက်ကို လော့ခ်ချထားသည်"</string> diff --git a/packages/SystemUI/res-keyguard/values-nb/strings.xml b/packages/SystemUI/res-keyguard/values-nb/strings.xml index a391b9293c05..8a3045aa656e 100644 --- a/packages/SystemUI/res-keyguard/values-nb/strings.xml +++ b/packages/SystemUI/res-keyguard/values-nb/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader raskt"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader sakte"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimaliserer batteritilstanden"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Koble til en batterilader."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Trykk på menyknappen for å låse opp."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Nettverket er låst"</string> diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml index 812aa38d4622..6f8a10885d5d 100644 --- a/packages/SystemUI/res-keyguard/values-ne/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज गरिँदै"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • द्रुत गतिमा चार्ज गरिँदै"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • मन्द गतिमा चार्ज गरिँदै"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ब्याट्री लामो समयसम्म टिक्ने बनाउन अप्टिमाइज गरिँदै छ"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"तपाईंको चार्जर जोड्नुहोस्।"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"अनलक गर्न मेनु थिच्नुहोस्।"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लक भएको छ"</string> diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml index f1c2033baaa8..a9fd827442e6 100644 --- a/packages/SystemUI/res-keyguard/values-nl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladen"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Snel opladen"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Langzaam opladen"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimaliseren voor batterijduur"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Sluit de oplader aan."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Druk op Menu om te ontgrendelen."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk vergrendeld"</string> diff --git a/packages/SystemUI/res-keyguard/values-or/strings.xml b/packages/SystemUI/res-keyguard/values-or/strings.xml index be6e2856bd27..385c13b4bc0e 100644 --- a/packages/SystemUI/res-keyguard/values-or/strings.xml +++ b/packages/SystemUI/res-keyguard/values-or/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଚାର୍ଜ ହେଉଛି"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଦ୍ରୁତ ଭାବେ ଚାର୍ଜ ହେଉଛି"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ବ୍ୟାଟେରୀ ହେଲ୍ଥ ପାଇଁ ଅପ୍ଟିମାଇଜ୍ ହେଉଛି"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"ଆପଣଙ୍କ ଚାର୍ଜର୍ ସଂଯୋଗ କରନ୍ତୁ।"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ଅନଲକ୍ କରିବା ପାଇଁ ମେନୁକୁ ଦବାନ୍ତୁ।"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ନେଟୱର୍କକୁ ଲକ୍ କରାଯାଇଛି"</string> diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml index a6ea6aaf4162..43d549c92e6b 100644 --- a/packages/SystemUI/res-keyguard/values-pa/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਤੇਜ਼ੀ ਨਾਲ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਹੌਲੀ-ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਬੈਟਰੀ ਸਥਿਤੀ ਲਈ ਅਨੁਕੂਲ ਬਣਾਇਆ ਜਾ ਰਿਹਾ"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"ਆਪਣਾ ਚਾਰਜਰ ਕਨੈਕਟ ਕਰੋ।"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ਅਣਲਾਕ ਕਰਨ ਲਈ \"ਮੀਨੂ\" ਦਬਾਓ।"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ਨੈੱਟਵਰਕ ਲਾਕ ਕੀਤਾ ਗਿਆ"</string> diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml index 9c6f27118600..76f755c2b96a 100644 --- a/packages/SystemUI/res-keyguard/values-pl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Szybkie ładowanie"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wolne ładowanie"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optymalizuję, by utrzymać baterię w dobrym stanie"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Podłącz ładowarkę."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Naciśnij Menu, aby odblokować."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieć zablokowana"</string> diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml index d2d5fb9d159a..29c46f8a592d 100644 --- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bateria limitada temporariamente"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Otimizando para integridade da bateria"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecte o seu carregador."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pressione Menu para desbloquear."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string> diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml index 7f0a4d883ee5..b15c9dc20772 100644 --- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar…"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar rapidamente…"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar lentamente…"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bateria limitada temporariamente."</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A otimizar o estado da bateria"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Ligue o carregador."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Prima Menu para desbloquear."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string> diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml index d2d5fb9d159a..29c46f8a592d 100644 --- a/packages/SystemUI/res-keyguard/values-pt/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bateria limitada temporariamente"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Otimizando para integridade da bateria"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecte o seu carregador."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pressione Menu para desbloquear."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string> diff --git a/packages/SystemUI/res-keyguard/values-ro/strings.xml b/packages/SystemUI/res-keyguard/values-ro/strings.xml index 572c1dbd0830..868d9f770980 100644 --- a/packages/SystemUI/res-keyguard/values-ro/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ro/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă rapid"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă lent"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se fac optimizări pentru buna funcționare a bateriei"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Conectați încărcătorul."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Apăsați pe Meniu pentru a debloca."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rețea blocată"</string> diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml index 2c87608f9b9b..24d762d00f5e 100644 --- a/packages/SystemUI/res-keyguard/values-ru/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"Идет зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"Идет быстрая зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"Идет медленная зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Оптимизация для увеличения срока службы батареи"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Подключите зарядное устройство."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Для разблокировки нажмите \"Меню\"."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сеть заблокирована"</string> diff --git a/packages/SystemUI/res-keyguard/values-si/strings.xml b/packages/SystemUI/res-keyguard/values-si/strings.xml index 8682192ce32a..3a6078224be2 100644 --- a/packages/SystemUI/res-keyguard/values-si/strings.xml +++ b/packages/SystemUI/res-keyguard/values-si/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ආරෝපණය වෙමින්"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • වේගයෙන් ආරෝපණය වෙමින්"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • සෙමින් ආරෝපණය වෙමින්"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • බැටරි සෞඛ්යය සඳහා ප්රශස්ත කරමින්"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"ඔබගේ ආරෝපකයට සම්බන්ධ කරන්න."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"අගුලු හැරීමට මෙනුව ඔබන්න."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ජාලය අගුළු දමා ඇත"</string> diff --git a/packages/SystemUI/res-keyguard/values-sk/strings.xml b/packages/SystemUI/res-keyguard/values-sk/strings.xml index d5e6093b1a83..98aa79a206f8 100644 --- a/packages/SystemUI/res-keyguard/values-sk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sk/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa rýchlo"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa pomaly"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimalizuje sa na zaistenie dobrého stavu batérie"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Pripojte nabíjačku."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Odomknete stlačením tlačidla ponuky."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieť je zablokovaná"</string> diff --git a/packages/SystemUI/res-keyguard/values-sl/strings.xml b/packages/SystemUI/res-keyguard/values-sl/strings.xml index 82d5c5493010..cd41d9b76ebb 100644 --- a/packages/SystemUI/res-keyguard/values-sl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sl/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • polnjenje"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • hitro polnjenje"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • počasno polnjenje"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizacija za ohranjanje zmogljivosti baterije"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite napajalnik."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Če želite odkleniti, pritisnite meni."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Omrežje je zaklenjeno"</string> diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml index a67413fdf5c2..0ad97a490a26 100644 --- a/packages/SystemUI/res-keyguard/values-sq/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me shpejtësi"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet ngadalë"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po optimizohet për integritetin e baterisë"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Lidh karikuesin."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Shtyp \"Meny\" për të shkyçur."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rrjeti është i kyçur"</string> diff --git a/packages/SystemUI/res-keyguard/values-sr/strings.xml b/packages/SystemUI/res-keyguard/values-sr/strings.xml index dec31650308e..90b8a3e362fd 100644 --- a/packages/SystemUI/res-keyguard/values-sr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sr/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Пуни се"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо се пуни"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Споро се пуни"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Оптимизује се ради доброг стања батерије"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Прикључите пуњач."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Притисните Мени да бисте откључали."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежа је закључана"</string> diff --git a/packages/SystemUI/res-keyguard/values-sv/strings.xml b/packages/SystemUI/res-keyguard/values-sv/strings.xml index 3ef2dfe87e88..80323e6e381d 100644 --- a/packages/SystemUI/res-keyguard/values-sv/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sv/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas snabbt"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas långsamt"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimerar batteriets livslängd"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Anslut laddaren."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Lås upp genom att trycka på Meny."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Nätverk låst"</string> diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml index 5c5fc10fe77e..da352620aace 100644 --- a/packages/SystemUI/res-keyguard/values-sw/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji kwa kasi"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji pole pole"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inaboresha muda wa kutumia betri"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Unganisha chaja yako."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Bonyeza Menyu ili kufungua."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mtandao umefungwa"</string> diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml index c188301bb7ed..ca9257707b69 100644 --- a/packages/SystemUI/res-keyguard/values-ta/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • சார்ஜாகிறது"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • வேகமாகச் சார்ஜாகிறது"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • மெதுவாகச் சார்ஜாகிறது"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • பேட்டரியின் ஆயுளை மேம்படுத்துகிறது"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"சார்ஜரை இணைக்கவும்."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"திறக்க, மெனுவை அழுத்தவும்."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"நெட்வொர்க் பூட்டப்பட்டது"</string> diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml index 27a5b285c485..c69a8f56b933 100644 --- a/packages/SystemUI/res-keyguard/values-te/strings.xml +++ b/packages/SystemUI/res-keyguard/values-te/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ఛార్జ్ అవుతోంది"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • వేగంగా ఛార్జ్ అవుతోంది"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • బ్యాటరీ జీవితకాలాన్ని ఆప్టిమైజ్ చేయడం కోసం"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"మీ ఛార్జర్ను కనెక్ట్ చేయండి."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"అన్లాక్ చేయడానికి మెనుని నొక్కండి."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"నెట్వర్క్ లాక్ చేయబడింది"</string> diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml index e506745d637e..4fd3dd177469 100644 --- a/packages/SystemUI/res-keyguard/values-th/strings.xml +++ b/packages/SystemUI/res-keyguard/values-th/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างเร็ว"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างช้าๆ"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังเพิ่มประสิทธิภาพแบตเตอรี่"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"เสียบที่ชาร์จของคุณ"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"กด \"เมนู\" เพื่อปลดล็อก"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"เครือข่ายถูกล็อก"</string> diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml index 912fd9529f09..8f26ea97bb61 100644 --- a/packages/SystemUI/res-keyguard/values-tl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nagcha-charge"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabilis na nagcha-charge"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabagal na nagcha-charge"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ino-optimize para sa tagal ng baterya"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Ikonekta ang iyong charger."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pindutin ang Menu upang i-unlock."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Naka-lock ang network"</string> diff --git a/packages/SystemUI/res-keyguard/values-tr/strings.xml b/packages/SystemUI/res-keyguard/values-tr/strings.xml index 5390c4c5c4eb..53a1cc7f8608 100644 --- a/packages/SystemUI/res-keyguard/values-tr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-tr/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj oluyor"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hızlı şarj oluyor"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş şarj oluyor"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pil sağlığı için optimize ediliyor"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Şarj cihazınızı takın."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Kilidi açmak için Menü\'ye basın."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Ağ kilitli"</string> diff --git a/packages/SystemUI/res-keyguard/values-uk/strings.xml b/packages/SystemUI/res-keyguard/values-uk/strings.xml index 6263d79fd645..a16576d37e9c 100644 --- a/packages/SystemUI/res-keyguard/values-uk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-uk/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Заряджання"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Швидке заряджання"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Повільне заряджання"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Стан акумулятора оптимізується"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Підключіть зарядний пристрій."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Натисніть меню, щоб розблокувати."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мережу заблоковано"</string> diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml index bf936cb86b51..a14f20df45d1 100644 --- a/packages/SystemUI/res-keyguard/values-ur/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • چارج ہو رہا ہے"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • تیزی سے چارج ہو رہا ہے"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آہستہ چارج ہو رہا ہے"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • بیٹری کی صحت کے لیے بہتر بنایا جا رہا ہے"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"اپنا چارجر منسلک کریں۔"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"غیر مقفل کرنے کیلئے مینو دبائیں۔"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"نیٹ ورک مقفل ہو گیا"</string> diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml index 0b23e16ddd2f..24a14c73d006 100644 --- a/packages/SystemUI/res-keyguard/values-uz/strings.xml +++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quvvat olmoqda"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Tezkor quvvat olmoqda"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sekin quvvat olmoqda"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Batareya quvvati muvozanatlanmoqda"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Quvvatlash moslamasini ulang."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Qulfdan chiqarish uchun Menyu tugmasini bosing."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tarmoq qulflangan"</string> diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml index 9357eba66432..32210664d383 100644 --- a/packages/SystemUI/res-keyguard/values-vi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc nhanh"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc chậm"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang tối ưu hóa để cải thiện độ bền của pin"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Kết nối bộ sạc của bạn."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Nhấn vào Menu để mở khóa."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mạng đã bị khóa"</string> diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml index 96728ab6cead..a3921d0a5657 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充电"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充电"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在慢速充电"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在针对电池状况进行优化"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"请连接充电器。"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按“菜单”即可解锁。"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"网络已锁定"</string> diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml index c683529d81ac..1054e36fc048 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充電"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充電"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> •正在慢速充電"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在優化電池狀態"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"請連接充電器。"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按下 [選單] 即可解鎖。"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"網絡已鎖定"</string> diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml index 7a3b5c52acf7..7efa2f934d95 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 慢速充電中"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 針對電池狀態進行最佳化調整"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"請連接充電器。"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按選單鍵解鎖。"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"網路已鎖定"</string> diff --git a/packages/SystemUI/res-keyguard/values-zu/strings.xml b/packages/SystemUI/res-keyguard/values-zu/strings.xml index ec38cbef456e..d87622af27bf 100644 --- a/packages/SystemUI/res-keyguard/values-zu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zu/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Iyashaja"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kaningi"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kancane"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ilungiselela impilo yebhethri"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Xhuma ishaja yakho."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Chofoza Menyu ukuvula."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Inethiwekhi ivaliwe"</string> diff --git a/packages/SystemUI/res/color/camera_foreground.xml b/packages/SystemUI/res/color/camera_foreground.xml new file mode 100644 index 000000000000..6e039cc1df1e --- /dev/null +++ b/packages/SystemUI/res/color/camera_foreground.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright 2010, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" + android:color="@color/control_default_foreground" /> + <item android:color="@color/GM2_grey_100" /> +</selector> diff --git a/packages/SystemUI/res/drawable/brightness_mirror_background.xml b/packages/SystemUI/res/drawable/brightness_mirror_background.xml index 43c9b73a6eff..4b225b763f3e 100644 --- a/packages/SystemUI/res/drawable/brightness_mirror_background.xml +++ b/packages/SystemUI/res/drawable/brightness_mirror_background.xml @@ -15,6 +15,6 @@ ~ limitations under the License --> <shape xmlns:android="http://schemas.android.com/apk/res/android"> - <solid android:color="@color/qs_background_dark" /> + <solid android:color="?android:attr/colorBackgroundFloating" /> <corners android:radius="8dp" /> </shape> diff --git a/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml b/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml index ca56ec17014b..108591beb05a 100644 --- a/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml +++ b/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml @@ -16,6 +16,27 @@ --> <layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:paddingMode="stack"> + <item android:id="@android:id/background" + android:gravity="center_vertical|fill_horizontal"> + <layer-list > + <item> + <shape + android:tint="?android:attr/colorControlActivated" + android:alpha="?android:attr/disabledAlpha"> + <size android:height="48dp" /> + <solid android:color="@color/white_disabled" /> + <corners android:radius="24dp" /> + </shape> + </item> + <item + android:gravity="center_vertical|start" + android:start="32dp"> + <com.android.systemui.util.AlphaTintDrawableWrapper + android:drawable="@drawable/ic_brightness" + android:tint="?android:attr/colorControlActivated" /> + </item> + </layer-list> + </item> <item android:id="@android:id/progress" android:gravity="center_vertical|fill_horizontal"> <clip @@ -24,13 +45,4 @@ android:gravity="left" /> </item> - <item android:id="@android:id/background" - android:gravity="center_vertical|fill_horizontal"> - <shape android:shape="rectangle" - android:tint="?android:attr/colorControlNormal"> - <size android:height="48dp" /> - <solid android:color="@color/white_disabled" /> - <corners android:radius="24dp" /> - </shape> - </item> </layer-list>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml index a38b8b4e62db..b5def5ebf539 100644 --- a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml +++ b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml @@ -15,10 +15,21 @@ ~ limitations under the License. --> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle" - android:tint="?android:attr/colorControlActivated"> - <size android:height="48dp" /> - <solid android:color="@android:color/white" /> - <corners android:radius="24dp"/> -</shape>
\ No newline at end of file +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/slider_foreground"> + <shape> + <size android:height="48dp" /> + <solid android:color="?android:attr/colorControlActivated" /> + <corners android:radius="24dp"/> + </shape> + </item> + <item + android:id="@+id/slider_icon" + android:gravity="center_vertical|start" + android:start="32dp"> + <com.android.systemui.util.AlphaTintDrawableWrapper + android:drawable="@drawable/ic_brightness" + android:tint="?android:attr/colorBackground" + android:alpha="0.8"/> + </item> +</layer-list>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml b/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml index 55116c6e549a..9f66581d8053 100644 --- a/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml +++ b/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml @@ -19,8 +19,8 @@ <shape android:shape="rectangle"> <solid android:color="@color/magnification_switch_button_color" /> <size - android:width="40dp" - android:height="40dp" /> + android:width="48dp" + android:height="48dp" /> </shape> </item> diff --git a/packages/SystemUI/res/drawable/ic_open_in_new_window.xml b/packages/SystemUI/res/drawable/ic_open_in_new_window.xml index 5f571cfa0197..659b02048c73 100644 --- a/packages/SystemUI/res/drawable/ic_open_in_new_window.xml +++ b/packages/SystemUI/res/drawable/ic_open_in_new_window.xml @@ -19,8 +19,8 @@ <shape android:shape="rectangle"> <solid android:color="@color/magnification_switch_button_color" /> <size - android:width="40dp" - android:height="40dp" /> + android:width="48dp" + android:height="48dp" /> </shape> </item> diff --git a/packages/SystemUI/res/drawable/people_space_activity_card.xml b/packages/SystemUI/res/drawable/people_space_activity_card.xml new file mode 100644 index 000000000000..81162d208b28 --- /dev/null +++ b/packages/SystemUI/res/drawable/people_space_activity_card.xml @@ -0,0 +1,19 @@ +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="?android:attr/colorAccent" /> + <corners android:radius="@dimen/people_space_widget_radius" /> +</shape>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/people_space_content_background.xml b/packages/SystemUI/res/drawable/people_space_content_background.xml new file mode 100644 index 000000000000..5310840939b8 --- /dev/null +++ b/packages/SystemUI/res/drawable/people_space_content_background.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<shape xmlns:android="http://schemas.android.com/apk/res/android" > + <solid android:color="?android:attr/colorControlHighlight" /> + <corners android:radius="@dimen/people_space_widget_radius" /> +</shape> diff --git a/packages/SystemUI/res/drawable/people_space_round_tile_view_card.xml b/packages/SystemUI/res/drawable/people_space_round_tile_view_card.xml new file mode 100644 index 000000000000..59af7750dada --- /dev/null +++ b/packages/SystemUI/res/drawable/people_space_round_tile_view_card.xml @@ -0,0 +1,19 @@ +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="?android:attr/colorBackground" /> + <corners android:radius="@dimen/people_space_widget_round_radius" /> +</shape>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/people_space_rounded_border.xml b/packages/SystemUI/res/drawable/people_space_rounded_border.xml new file mode 100644 index 000000000000..9956bc2eb2ac --- /dev/null +++ b/packages/SystemUI/res/drawable/people_space_rounded_border.xml @@ -0,0 +1,19 @@ +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="oval"> + <solid android:color="?android:attr/colorBackground" /> +</shape>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/people_space_tile_view_card.xml b/packages/SystemUI/res/drawable/people_space_tile_view_card.xml index 4772ae76179e..8fd4388fd01d 100644 --- a/packages/SystemUI/res/drawable/people_space_tile_view_card.xml +++ b/packages/SystemUI/res/drawable/people_space_tile_view_card.xml @@ -14,6 +14,6 @@ ~ limitations under the License. --> <shape xmlns:android="http://schemas.android.com/apk/res/android"> - <solid android:color="@android:color/white" /> + <solid android:color="?android:attr/colorBackground" /> <corners android:radius="@dimen/people_space_widget_radius" /> </shape>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/people_space_widget_background.xml b/packages/SystemUI/res/drawable/people_space_widget_background.xml index b9293598bd00..fa457187990e 100644 --- a/packages/SystemUI/res/drawable/people_space_widget_background.xml +++ b/packages/SystemUI/res/drawable/people_space_widget_background.xml @@ -18,7 +18,7 @@ android:shape="rectangle" > <solid android:color="?android:attr/colorControlNormal" /> - <corners android:radius="@dimen/people_space_widget_radius" /> + <corners android:radius="@dimen/people_space_widget_background_padding" /> <padding android:left="@dimen/people_space_widget_background_padding" android:top="@dimen/people_space_widget_background_padding" diff --git a/packages/SystemUI/res/drawable/qs_background_primary.xml b/packages/SystemUI/res/drawable/qs_background_primary.xml deleted file mode 100644 index dd74cadd0955..000000000000 --- a/packages/SystemUI/res/drawable/qs_background_primary.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2014 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. ---> -<inset xmlns:android="http://schemas.android.com/apk/res/android"> - <shape> - <solid android:color="@color/qs_background_dark"/> - <corners android:radius="?android:attr/dialogCornerRadius" /> - </shape> -</inset> diff --git a/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml b/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml index 215dee41d548..c2d0841a1b8f 100644 --- a/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml +++ b/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml @@ -15,7 +15,7 @@ --> <inset xmlns:android="http://schemas.android.com/apk/res/android"> <shape> - <solid android:color="@color/qs_customize_background"/> + <solid android:color="?android:attr/colorBackgroundFloating"/> <corners android:radius="?android:attr/dialogCornerRadius" /> </shape> </inset> diff --git a/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml b/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml index 648d45b4f903..7cb44b3e1500 100644 --- a/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml +++ b/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml @@ -15,7 +15,7 @@ --> <inset xmlns:android="http://schemas.android.com/apk/res/android"> <shape> - <solid android:color="@color/qs_customize_background"/> + <solid android:color="?android:attr/colorBackgroundFloating"/> <corners android:topLeftRadius="?android:attr/dialogCornerRadius" android:topRightRadius="?android:attr/dialogCornerRadius" /> diff --git a/packages/SystemUI/res/drawable/qs_detail_background.xml b/packages/SystemUI/res/drawable/qs_detail_background.xml index 672abf14774e..76045e4126cb 100644 --- a/packages/SystemUI/res/drawable/qs_detail_background.xml +++ b/packages/SystemUI/res/drawable/qs_detail_background.xml @@ -25,7 +25,7 @@ Copyright (C) 2014 The Android Open Source Project <item> <inset> <shape> - <solid android:color="?android:attr/colorPrimary"/> + <solid android:color="?android:attr/colorBackgroundFloating"/> <corners android:radius="?android:attr/dialogCornerRadius" /> </shape> </inset> diff --git a/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml b/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml index 509cd1fb5db7..59dad0e9ee15 100644 --- a/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml +++ b/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml @@ -17,6 +17,6 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <solid - android:color="#e5e5e5" /> + android:color="?android:attr/textColorPrimary" /> <corners android:radius="2dp" /> </shape> diff --git a/packages/SystemUI/res/layout-sw600dp-land/global_actions_grid_v2.xml b/packages/SystemUI/res/layout-sw600dp-land/global_actions_grid_v2.xml new file mode 100644 index 000000000000..953a29e3a07e --- /dev/null +++ b/packages/SystemUI/res/layout-sw600dp-land/global_actions_grid_v2.xml @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/global_actions_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal"> + + <LinearLayout + android:layout_weight="1" + android:layout_height="match_parent" + android:layout_width="0dp" + android:clipChildren="false" + android:orientation="vertical" + android:clipToPadding="false" + android:id="@+id/controls_pane" + > + <LinearLayout + android:id="@+id/global_actions_controls" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"/> + </LinearLayout> + + <LinearLayout + android:layout_weight="1" + android:layout_height="match_parent" + android:layout_width="0dp" + android:orientation="vertical" + android:id="@+id/nfc_pane" + > + <include layout="@layout/global_actions_view" /> + + <include layout="@layout/global_actions_lock_view" /> + + <LinearLayout + android:id="@+id/global_actions_grid_root" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:clipChildren="false" + android:orientation="vertical" + android:clipToPadding="false"> + + <FrameLayout + android:id="@+id/global_actions_wallet" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> + + </LinearLayout> + + </LinearLayout> +</LinearLayout> diff --git a/packages/SystemUI/res/layout-sw600dp/global_actions_controls_list_view.xml b/packages/SystemUI/res/layout-sw600dp/global_actions_controls_list_view.xml new file mode 100644 index 000000000000..ef49b9c3b6ad --- /dev/null +++ b/packages/SystemUI/res/layout-sw600dp/global_actions_controls_list_view.xml @@ -0,0 +1,30 @@ +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<com.android.systemui.globalactions.MinHeightScrollView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:scrollbars="none"> + <LinearLayout + android:id="@+id/global_actions_controls_list" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_marginLeft="@dimen/global_actions_side_margin" + android:layout_marginRight="@dimen/global_actions_side_margin" /> +</com.android.systemui.globalactions.MinHeightScrollView>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout-sw600dp/global_actions_grid_v2.xml b/packages/SystemUI/res/layout-sw600dp/global_actions_grid_v2.xml new file mode 100644 index 000000000000..6ffcef7b24e6 --- /dev/null +++ b/packages/SystemUI/res/layout-sw600dp/global_actions_grid_v2.xml @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/global_actions_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <LinearLayout + android:layout_weight="1" + android:layout_height="0dp" + android:layout_width="match_parent" + android:orientation="vertical" + android:id="@+id/nfc_pane" + > + + <include layout="@layout/global_actions_view" /> + + <include layout="@layout/global_actions_lock_view" /> + + + <com.android.systemui.globalactions.MinHeightScrollView + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:scrollbars="none"> + + <LinearLayout + android:id="@+id/global_actions_grid_root" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:clipChildren="false" + android:orientation="vertical" + android:clipToPadding="false"> + + <FrameLayout + android:id="@+id/global_actions_wallet" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> + + </LinearLayout> + </com.android.systemui.globalactions.MinHeightScrollView> + + </LinearLayout> + + <LinearLayout + android:layout_weight="1" + android:layout_height="0dp" + android:layout_width="match_parent" + android:orientation="vertical" + android:id="@+id/controls_pane" + android:clipToPadding="false" + android:clipChildren="false"> + <LinearLayout + android:id="@+id/global_actions_controls" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"/> + </LinearLayout> +</LinearLayout> diff --git a/packages/SystemUI/res/layout/controls_with_favorites.xml b/packages/SystemUI/res/layout/controls_with_favorites.xml index 065ff68774eb..b060afdc18e3 100644 --- a/packages/SystemUI/res/layout/controls_with_favorites.xml +++ b/packages/SystemUI/res/layout/controls_with_favorites.xml @@ -58,11 +58,5 @@ android:background="?android:attr/selectableItemBackgroundBorderless" /> </LinearLayout> - <LinearLayout - android:id="@+id/global_actions_controls_list" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:layout_marginLeft="@dimen/global_actions_side_margin" - android:layout_marginRight="@dimen/global_actions_side_margin" /> + <include layout="@layout/global_actions_controls_list_view" /> </merge> diff --git a/packages/SystemUI/res/layout/feedback_info.xml b/packages/SystemUI/res/layout/feedback_info.xml index 7047c1b21961..753f56a18348 100644 --- a/packages/SystemUI/res/layout/feedback_info.xml +++ b/packages/SystemUI/res/layout/feedback_info.xml @@ -109,24 +109,4 @@ style="@style/TextAppearance.NotificationInfo.Button"/> </LinearLayout> - <!-- Done button --> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="@dimen/notification_guts_button_spacing" - android:layout_marginBottom="@dimen/notification_guts_button_spacing" - android:gravity="end" - android:orientation="horizontal"> - - <TextView - android:id="@+id/ok" - android:text="@string/feedback_ok" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:background="@drawable/ripple_drawable" - android:minWidth="48dp" - android:layout_marginStart="8dp" - android:layout_marginEnd="-8dp" - style="@style/TextAppearance.NotificationInfo.Button"/> - </LinearLayout> </com.android.systemui.statusbar.notification.row.FeedbackInfo> diff --git a/packages/SystemUI/res/layout/global_actions_controls_list_view.xml b/packages/SystemUI/res/layout/global_actions_controls_list_view.xml new file mode 100644 index 000000000000..e1c2611cc4d4 --- /dev/null +++ b/packages/SystemUI/res/layout/global_actions_controls_list_view.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/global_actions_controls_list" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_marginLeft="@dimen/global_actions_side_margin" + android:layout_marginRight="@dimen/global_actions_side_margin" />
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml b/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml index 99b9ced53090..14a5e584a06d 100644 --- a/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml +++ b/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml @@ -18,7 +18,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="0dp" android:layout_weight="1" - android:layout_height="98dp" + android:layout_height="@dimen/global_actions_grid_item_layout_height" android:gravity="bottom|center_horizontal" android:orientation="vertical" android:paddingTop="12dp" diff --git a/packages/SystemUI/res/layout/people_space_activity.xml b/packages/SystemUI/res/layout/people_space_activity.xml index 67ecdaa5d7b6..07af01b0db72 100644 --- a/packages/SystemUI/res/layout/people_space_activity.xml +++ b/packages/SystemUI/res/layout/people_space_activity.xml @@ -17,8 +17,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/scroll" android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="@android:color/holo_blue_light"> + android:layout_height="match_parent"> <LinearLayout android:id="@+id/people_space_layout" @@ -30,16 +29,15 @@ android:clipChildren="false" android:clipToPadding="false"> - <ImageView - android:id="@+id/people_space_cloud" - android:layout_width="67dp" - android:layout_height="67dp" + <TextView + android:id="@+id/select_conversation" + android:text="@string/select_conversation_text" + android:layout_width="match_parent" + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" + android:textSize="24sp" + android:layout_height="wrap_content" android:layout_gravity="center_horizontal" - android:scaleType="fitCenter" - android:focusable="false" - android:paddingBottom="16dp" - android:tint="?android:attr/colorControlNormal" - android:src="@drawable/cloud" /> + android:paddingBottom="16dp" /> </LinearLayout> </androidx.core.widget.NestedScrollView>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/people_space_large_avatar_tile.xml b/packages/SystemUI/res/layout/people_space_large_avatar_tile.xml new file mode 100644 index 000000000000..e9f3424547fa --- /dev/null +++ b/packages/SystemUI/res/layout/people_space_large_avatar_tile.xml @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + <LinearLayout + android:background="@drawable/people_space_round_tile_view_card" + android:id="@+id/item" + android:paddingVertical="6dp" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <LinearLayout + android:orientation="horizontal" + android:gravity="center_vertical" + android:paddingStart="12dp" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <ImageView + android:id="@+id/person_icon" + android:layout_width="60dp" + android:layout_height="60dp" /> + + <LinearLayout + android:background="@drawable/people_space_rounded_border" + android:layout_marginStart="-12dp" + android:layout_marginTop="28dp" + android:layout_marginBottom="14dp" + android:layout_width="16dp" + android:layout_height="16dp"> + + <ImageView + android:id="@+id/package_icon" + android:layout_width="12dp" + android:layout_marginStart="2dp" + android:layout_marginEnd="2dp" + android:layout_marginBottom="2dp" + android:layout_marginTop="2dp" + android:layout_height="12dp" /> + </LinearLayout> + + <LinearLayout + android:orientation="vertical" + android:paddingStart="8dp" + android:paddingEnd="12dp" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <TextView + android:id="@+id/name" + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" + android:textColor="?android:attr/textColorPrimary" + android:textSize="16sp" + android:maxLines="1" + android:ellipsize="end" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <TextView + android:id="@+id/status" + android:textColor="?android:attr/textColorSecondary" + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" + android:paddingVertical="3dp" + android:textSize="12sp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:maxLines="3" + android:ellipsize="end" /> + </LinearLayout> + </LinearLayout> + </LinearLayout> +</LinearLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml b/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml new file mode 100644 index 000000000000..f47483054ea3 --- /dev/null +++ b/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + <LinearLayout + android:background="@drawable/people_space_tile_view_card" + android:id="@+id/item" + android:orientation="vertical" + android:paddingTop="6dp" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <LinearLayout + android:orientation="horizontal" + android:paddingHorizontal="12dp" + android:paddingBottom="4dp" + android:gravity="top" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <ImageView + android:id="@+id/person_icon" + android:layout_width="34dp" + android:layout_height="34dp" /> + + <LinearLayout + android:background="@drawable/people_space_rounded_border" + android:layout_marginStart="-5dp" + android:layout_marginTop="18dp" + android:layout_width="8dp" + android:layout_height="8dp"> + + <ImageView + android:id="@+id/package_icon" + android:layout_width="6dp" + android:layout_marginEnd="1dp" + android:layout_marginStart="1dp" + android:layout_marginBottom="1dp" + android:layout_marginTop="1dp" + android:layout_height="6dp" /> + </LinearLayout> + + <LinearLayout + android:orientation="vertical" + android:paddingStart="6dp" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <TextView + android:id="@+id/name" + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" + android:textColor="?android:attr/textColorPrimary" + android:textSize="14sp" + android:maxLines="1" + android:ellipsize="end" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <TextView + android:id="@+id/time" + android:textColor="?android:attr/textColorSecondary" + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" + android:textSize="10sp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:maxLines="1" + android:ellipsize="end" /> + </LinearLayout> + </LinearLayout> + <TextView + android:id="@+id/content" + android:paddingVertical="3dp" + android:paddingHorizontal="12dp" + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" + android:background="@drawable/people_space_content_background" + android:textSize="14sp" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:maxLines="2" + android:ellipsize="end" /> + </LinearLayout> +</LinearLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/people_space_tile_view.xml b/packages/SystemUI/res/layout/people_space_tile_view.xml index 80bb07070b31..c751e7d08fd1 100644 --- a/packages/SystemUI/res/layout/people_space_tile_view.xml +++ b/packages/SystemUI/res/layout/people_space_tile_view.xml @@ -20,46 +20,53 @@ android:orientation="vertical"> <LinearLayout - android:background="@drawable/people_space_tile_view_card" android:orientation="vertical" - android:padding="16dp" - android:layout_marginBottom="24dp" - android:layout_width="match_parent" - android:layout_height="wrap_content" + android:background="@drawable/people_space_activity_card" + android:padding="12dp" android:elevation="4dp" - android:gravity="start"> + android:layout_marginBottom="12dp" + android:layout_width="match_parent" + android:layout_height="wrap_content"> - <ImageView - android:id="@+id/tile_view_package_icon" - android:layout_width="32dp" - android:layout_height="32dp" - android:layout_gravity="end" /> + <LinearLayout + android:orientation="horizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="start"> - <ImageView - android:id="@+id/tile_view_person_icon" - android:layout_width="32dp" - android:layout_height="32dp" - android:layout_gravity="start" /> + <ImageView + android:id="@+id/tile_view_person_icon" + android:layout_width="48dp" + android:layout_height="48dp" /> - <TextView - android:id="@+id/tile_view_name" - android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" - android:paddingVertical="4dp" - android:textSize="22sp" - android:textColor="?android:attr/textColorPrimary" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="start" /> + <ImageView + android:id="@+id/tile_view_package_icon" + android:layout_width="16dp" + android:layout_marginStart="-8dp" + android:layout_height="16dp" /> - <TextView - android:id="@+id/tile_view_status" - android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" - android:paddingVertical="4dp" - android:textSize="16sp" - android:textColor="?android:attr/textColorSecondary" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:ellipsize="end" - android:layout_gravity="start" /> + <LinearLayout + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <TextView + android:id="@+id/tile_view_name" + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" + android:paddingHorizontal="16dp" + android:textSize="22sp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <TextView + android:id="@+id/tile_view_status" + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" + android:paddingVertical="4dp" + android:textSize="12sp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ellipsize="end" /> + </LinearLayout> + </LinearLayout> </LinearLayout> </LinearLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/people_space_widget.xml b/packages/SystemUI/res/layout/people_space_widget.xml index b417fcf6424d..f4db321b8714 100644 --- a/packages/SystemUI/res/layout/people_space_widget.xml +++ b/packages/SystemUI/res/layout/people_space_widget.xml @@ -22,6 +22,6 @@ android:background="@drawable/people_space_widget_background" android:clipChildren="false" android:clipToPadding="false" - android:padding="5dp" + android:padding="2dp" android:divider="@null" android:dividerHeight="0dp"/>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/people_space_widget_item.xml b/packages/SystemUI/res/layout/people_space_widget_item.xml index e4de6f91769c..170386f5ecc5 100644 --- a/packages/SystemUI/res/layout/people_space_widget_item.xml +++ b/packages/SystemUI/res/layout/people_space_widget_item.xml @@ -16,44 +16,77 @@ --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" + android:padding="4dp" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:background="@drawable/people_space_tile_view_card" android:id="@+id/item" android:orientation="vertical" - android:padding="6dp" - android:layout_marginBottom="6dp" + android:padding="4dp" + android:layout_marginBottom="2dp" android:elevation="4dp" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:gravity="start"> - <ImageView - android:id="@+id/package_icon" - android:layout_width="30dp" - android:layout_height="30dp" - android:layout_gravity="end" /> - <ImageView - android:id="@+id/person_icon" - android:layout_width="30dp" - android:layout_height="30dp" - android:layout_gravity="start" /> - <TextView - android:id="@+id/name" - android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" - android:textSize="18sp" - android:textColor="?android:attr/textColorPrimary" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="start" /> - <TextView - android:id="@+id/status" - android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" - android:paddingVertical="2dp" - android:textSize="14sp" - android:textColor="?android:attr/textColorSecondary" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="start" /> + android:layout_height="wrap_content"> + + <LinearLayout + android:orientation="horizontal" + android:gravity="center_vertical" + android:paddingStart="12dp" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <ImageView + android:id="@+id/person_icon" + android:layout_width="60dp" + android:layout_height="60dp" /> + + <LinearLayout + android:background="@drawable/people_space_rounded_border" + android:layout_marginStart="-12dp" + android:layout_marginTop="28dp" + android:layout_marginBottom="14dp" + android:layout_width="16dp" + android:layout_height="16dp"> + + <ImageView + android:id="@+id/package_icon" + android:layout_width="12dp" + android:layout_marginStart="2dp" + android:layout_marginEnd="2dp" + android:layout_marginBottom="2dp" + android:layout_marginTop="2dp" + android:layout_height="12dp" /> + </LinearLayout> + + <LinearLayout + android:orientation="vertical" + android:paddingStart="8dp" + android:paddingEnd="12dp" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <TextView + android:id="@+id/name" + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" + android:textColor="?android:attr/textColorPrimary" + android:textSize="16sp" + android:maxLines="1" + android:ellipsize="end" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <TextView + android:id="@+id/status" + android:textColor="?android:attr/textColorSecondary" + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" + android:paddingVertical="2dp" + android:textSize="12sp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:maxLines="3" + android:ellipsize="end" /> + </LinearLayout> + </LinearLayout> </LinearLayout> </LinearLayout> diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml index 89bf12d70b84..387f2f2ccfc7 100644 --- a/packages/SystemUI/res/layout/qs_panel.xml +++ b/packages/SystemUI/res/layout/qs_panel.xml @@ -25,9 +25,7 @@ <View android:id="@+id/quick_settings_background" android:layout_width="match_parent" - android:layout_height="0dp" - android:elevation="4dp" - android:background="@drawable/qs_background_primary" /> + android:layout_height="0dp" /> <com.android.systemui.qs.NonInterceptingScrollView android:id="@+id/expanded_qs_scroll_view" diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml index e08b44af1068..4f4b2af09799 100644 --- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml +++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml @@ -14,10 +14,10 @@ limitations under the License. --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_height="wrap_content" - android:layout_width="match_parent" - android:layout_gravity="center" - style="@style/BrightnessDialogContainer"> + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_gravity="center" + style="@style/BrightnessDialogContainer"> <com.android.systemui.settings.brightness.BrightnessSliderView android:id="@+id/brightness_slider" @@ -38,16 +38,5 @@ android:progressDrawable="@drawable/brightness_progress_drawable_thick" android:splitTrack="false" /> - - <ImageView - android:id="@+id/image" - android:layout_width="24dp" - android:layout_height="24dp" - android:layout_marginLeft="48dp" - android:layout_gravity="center_vertical" - android:src="@drawable/ic_brightness" - android:tint="?android:attr/textColorTertiary" - android:visibility="visible" - /> </com.android.systemui.settings.brightness.BrightnessSliderView> </FrameLayout> diff --git a/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml b/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml index 69beffe0798c..6f9d7457e245 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml @@ -25,5 +25,4 @@ android:layout_marginTop="@dimen/notification_side_paddings" android:layout_marginLeft="@dimen/notification_side_paddings" android:layout_marginRight="@dimen/notification_side_paddings" - android:visibility="gone" - android:background="@drawable/qs_background_primary"/> + android:visibility="gone"/> diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 1fab4780a4c1..ce47ed8dcfe7 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Skermkiekie is gestoor"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tik om jou skermkiekie te bekyk"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Kon nie skermkiekie stoor nie"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Toestel moet ontsluit word voordat skermkiekie gestoor kan word"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Probeer weer skermkiekie neem"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Kan weens beperkte bergingspasie nie skermkiekie stoor nie"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Die program of jou organisasie laat nie toe dat skermkiekies geneem word nie"</string> diff --git a/packages/SystemUI/res/values-af/strings_tv.xml b/packages/SystemUI/res/values-af/strings_tv.xml index eb6316502e2d..2e9400e2e5b6 100644 --- a/packages/SystemUI/res/values-af/strings_tv.xml +++ b/packages/SystemUI/res/values-af/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is gekoppel"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is ontkoppel"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Kennisgewings"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Geen kennisgewings nie"</string> </resources> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 5153904f3e02..2573175f080a 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"ቅጽበታዊ ገጽ እይታ ተቀምጧል"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"የእርስዎን ቅጽበታዊ ገጽ እይታ ለማየት መታ ያድርጉ"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"ቅጽበታዊ ገጽ ዕይታን ማስቀመጥ አልተቻለም"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ቅጽበታዊ ገጽ እይታ ከመቀመጡ በፊት መሳሪያ መከፈት አለበት"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ቅጽበታዊ ገጽ ዕይታን እንደገና ማንሳት ይሞክሩ"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ባለው ውሱን የማከማቻ ቦታ ምክንያት ቅጽበታዊ ገጽ ዕይታን ማስቀመጥ አይችልም"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ቅጽበታዊ ገጽ እይታዎችን ማንሳት በመተግበሪያው ወይም በእርስዎ ድርጅት አይፈቀድም"</string> diff --git a/packages/SystemUI/res/values-am/strings_tv.xml b/packages/SystemUI/res/values-am/strings_tv.xml index 3ba5a62a52d6..71d887d09752 100644 --- a/packages/SystemUI/res/values-am/strings_tv.xml +++ b/packages/SystemUI/res/values-am/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ተያይዟል"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ተቋርቷል"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"በ<xliff:g id="VPN_APP">%1$s</xliff:g> በኩል"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"ማሳወቂያዎች"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ምንም ማሳወቂያዎች የሉም"</string> </resources> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index f6a1cf5e711b..f0d0b84ba087 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"تم حفظ لقطة الشاشة."</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"انقر لعرض لقطة الشاشة."</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"تعذّر حفظ لقطة الشاشة"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"يجب أن يتم فتح قفل الجهاز قبل حفظ لقطة الشاشة."</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"جرّب أخذ لقطة الشاشة مرة أخرى"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"يتعذر حفظ لقطة الشاشة لأن مساحة التخزين المتاحة محدودة."</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"يحظر التطبيق أو تحظر مؤسستك التقاط لقطات شاشة"</string> diff --git a/packages/SystemUI/res/values-ar/strings_tv.xml b/packages/SystemUI/res/values-ar/strings_tv.xml index 15ccb94a04a8..7297c898f99a 100644 --- a/packages/SystemUI/res/values-ar/strings_tv.xml +++ b/packages/SystemUI/res/values-ar/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"الشبكة الافتراضية الخاصة (VPN) متصلة."</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"الشبكة الافتراضية الخاصة (VPN) غير متصلة."</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"عبر <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"الإشعارات"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ما من إشعارات"</string> </resources> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index b84f40972af5..366a86f571b5 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"স্ক্ৰীণশ্বট ছেভ কৰা হ’ল"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"আপোনাৰ স্ক্ৰীণশ্বট চাবলৈ টিপক"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"স্ক্ৰীণশ্বট ছেভ কৰিব পৰা নগ\'ল"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"স্ক্ৰীনশ্বট ছেভ কৰিবলৈ ডিভাইচটো আনলক কৰিবই লাগিব"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"স্ক্ৰীণশ্বট আকৌ ল\'বলৈ চেষ্টা কৰক"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"সঞ্চয়াগাৰত সীমিত খালী ঠাই থকাৰ বাবে স্ক্ৰীণশ্বট ছেভ কৰিব পৰা নগ\'ল"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"এপটোৱে বা আপোনাৰ প্ৰতিষ্ঠানে স্ক্ৰীণশ্বট ল\'বলৈ অনুমতি নিদিয়ে"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"সাধাৰণ বার্তাসমূহ"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"সঞ্চয়াগাৰ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"ইংগিতবোৰ"</string> - <string name="instant_apps" msgid="8337185853050247304">"তাৎক্ষণিক এপসমূহ"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> চলি আছে"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ইনষ্ট\'ল নকৰাকৈয়েই এপটো খোলা হৈছে।"</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ইনষ্ট\'ল নকৰাকৈয়েই এপটো খোলা হৈছে। অধিক জানিবলৈ টিপক।"</string> diff --git a/packages/SystemUI/res/values-as/strings_tv.xml b/packages/SystemUI/res/values-as/strings_tv.xml index f7afcfa5c6dc..859ea2c65093 100644 --- a/packages/SystemUI/res/values-as/strings_tv.xml +++ b/packages/SystemUI/res/values-as/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"ভিপিএন সংযোগ হৈ আছে"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"ভিপিএনৰ সংযোগ বিচ্ছিন্ন হৈছে"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>ৰ জৰিয়তে"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"জাননী"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"কোনো জাননী নাই"</string> </resources> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index a3292888e231..d2019261385f 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Skrinşot yadda saxlandı"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Skrinşotunuza baxmaq üçün klikləyin"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Skrinşotu yadda saxlamaq alınmadı"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Skrinşotu saxlamazdan əvvəl cihaz kiliddən çıxarılmalıdır"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Skrinşotu yenidən çəkin"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Yaddaş ehtiyatının az olması səbəbindən skrinşotu yadda saxlamaq olmur"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Skrinşot çəkməyə tətbiq və ya təşkilat tərəfindən icazə verilmir"</string> diff --git a/packages/SystemUI/res/values-az/strings_tv.xml b/packages/SystemUI/res/values-az/strings_tv.xml index cd9935f5f239..1f1b6491b533 100644 --- a/packages/SystemUI/res/values-az/strings_tv.xml +++ b/packages/SystemUI/res/values-az/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN qoşulub"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ayrılıb"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> vasitəsilə"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Bildirişlər"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Bildiriş yoxdur"</string> </resources> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index d800e8de8c2d..aa44b36819d5 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimak ekrana je sačuvan"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Dodirnite da biste videli snimak ekrana"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Čuvanje snimka ekrana nije uspelo"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Uređaj mora da bude otključan da bi snimak ekrana mogao da se sačuva"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Probajte da ponovo napravite snimak ekrana"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Čuvanje snimka ekrana nije uspelo zbog ograničenog memorijskog prostora"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikacija ili organizacija ne dozvoljavaju pravljenje snimaka ekrana"</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml index 8122e4d19ac0..2eaa4996b101 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN je povezan"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Veza sa VPN-om je prekinuta"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Preko: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Obaveštenja"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nema obaveštenja"</string> </resources> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 9fd9a5ec4c9b..bc28f9b1375c 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Здымак экрана захаваны"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Дакраніцеся, каб прагледзець здымак экрана"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Не атрымалася зрабіць здымак экрана"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Перад захаваннем здымка экрана трэба разблакіраваць прыладу"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Паспрабуйце зрабіць здымак экрана яшчэ раз"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Немагчыма захаваць здымак экрана, бо мала месца ў сховішчы"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Рабіць здымкі экрана не дазваляе праграма ці ваша арганізацыя"</string> diff --git a/packages/SystemUI/res/values-be/strings_tv.xml b/packages/SystemUI/res/values-be/strings_tv.xml index 1016b8c59628..21a2e6ed1d42 100644 --- a/packages/SystemUI/res/values-be/strings_tv.xml +++ b/packages/SystemUI/res/values-be/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN падключаны"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN адключаны"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Праз <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Апавяшчэнні"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Апавяшчэнняў няма"</string> </resources> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 78a826b6a898..faa7e560928c 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Екранната снимка е запазена"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Докоснете, за да видите екранната снимка"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Не можа да се запази екранна снимка"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"За да бъде запазена екранната снимка, устройството трябва да бъде отключено"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Опитайте да направите екранна снимка отново"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Екранната снимка не може да се запази поради ограничено място в хранилището"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Правенето на екранни снимки не е разрешено от приложението или организацията ви"</string> diff --git a/packages/SystemUI/res/values-bg/strings_tv.xml b/packages/SystemUI/res/values-bg/strings_tv.xml index 6f6b8248ce79..b7af7cb26c41 100644 --- a/packages/SystemUI/res/values-bg/strings_tv.xml +++ b/packages/SystemUI/res/values-bg/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN е свързана"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Връзката с VPN е прекратена"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Чрез <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Известия"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Няма известия"</string> </resources> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 92e0c1dd9613..04fd1ca184ae 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"স্ক্রিনশট সেভ করা হয়েছে"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"স্ক্রিনশটটি দেখতে ট্যাপ করুন"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"স্ক্রিনশট সেভ করা যায়নি"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"স্ক্রিনশট সেভ করার আগে ডিভাইসটি অবশ্যই আনলক করতে হবে"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"আবার স্ক্রিনশট নেওয়ার চেষ্টা করুন"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"বেশি জায়গা নেই তাই স্ক্রিনশটটি সেভ করা যাবে না৷"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"এই অ্যাপ বা আপনার প্রতিষ্ঠান স্ক্রিনশট নেওয়ার অনুমতি দেয়নি"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"সাধারণ বার্তাগুলি"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"স্টোরেজ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"হিন্ট"</string> - <string name="instant_apps" msgid="8337185853050247304">"ইনস্ট্যান্ট অ্যাপ"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> চলছে"</string> <string name="instant_apps_message" msgid="6112428971833011754">"অ্যাপটি ইনস্টল না করে চালু করা হয়েছে।"</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"অ্যাপটি ইনস্টল না করে চালু করা হয়েছে। আরও জানতে ট্যাপ করুন।"</string> diff --git a/packages/SystemUI/res/values-bn/strings_tv.xml b/packages/SystemUI/res/values-bn/strings_tv.xml index 1c26840f1d18..38c24ace782e 100644 --- a/packages/SystemUI/res/values-bn/strings_tv.xml +++ b/packages/SystemUI/res/values-bn/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN কানেক্ট করা হয়েছে"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ডিসকানেক্ট করা হয়েছে"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-এর মাধ্যমে"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"বিজ্ঞপ্তি"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"কোনও বিজ্ঞপ্তি নেই"</string> </resources> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 1179a92547f0..e2a623c110c6 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimak ekrana je sačuvan"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Dodirnite za prikaz snimka ekrana"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Nije moguće sačuvati snimak ekrana"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Morate otključati uređaj da možete sačuvati snimak ekrana"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Pokušajte ponovo snimiti ekran"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Snimak ekrana se ne može sačuvati zbog manjka prostora za pohranu"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ova aplikacija ili vaša organizacija ne dozvoljavaju snimanje ekrana"</string> diff --git a/packages/SystemUI/res/values-bs/strings_tv.xml b/packages/SystemUI/res/values-bs/strings_tv.xml index 7507746b4e65..01916a1dea8c 100644 --- a/packages/SystemUI/res/values-bs/strings_tv.xml +++ b/packages/SystemUI/res/values-bs/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN je povezan"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Veza s VPN-om je prekinuta"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Putem: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Obavještenja"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nema obavještenja"</string> </resources> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index ca6316252588..1fa0c9a762ef 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"S\'ha desat la captura de pantalla"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Toca per veure la captura de pantalla"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"No s\'ha pogut desar la captura de pantalla"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"El dispositiu ha d\'estar desbloquejat abans que la captura de pantalla es pugui desar"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prova de tornar a fer una captura de pantalla"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"La captura de pantalla no es pot desar perquè no hi ha prou espai d\'emmagatzematge"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'aplicació o la teva organització no permeten fer captures de pantalla"</string> diff --git a/packages/SystemUI/res/values-ca/strings_tv.xml b/packages/SystemUI/res/values-ca/strings_tv.xml index 14bc9472f260..a0607854c0e2 100644 --- a/packages/SystemUI/res/values-ca/strings_tv.xml +++ b/packages/SystemUI/res/values-ca/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"La VPN està connectada"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"La VPN està desconnectada"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Mitjançant <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificacions"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Cap notificació"</string> </resources> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index aa6459e76548..e414fd00291d 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Snímek obrazovky byl uložen"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Klepnutím snímek obrazovky zobrazíte"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Snímek obrazovky se nepodařilo uložit"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Aby bylo možné uložit screenshot, zařízení musí být odemknuto"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Zkuste snímek pořídit znovu"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Snímek obrazovky kvůli nedostatku místa v úložišti nelze uložit"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikace nebo organizace zakazuje pořizování snímků obrazovky"</string> diff --git a/packages/SystemUI/res/values-cs/strings_tv.xml b/packages/SystemUI/res/values-cs/strings_tv.xml index ad869b1399fa..0a9850c7b7a7 100644 --- a/packages/SystemUI/res/values-cs/strings_tv.xml +++ b/packages/SystemUI/res/values-cs/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Síť VPN je připojena"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Síť VPN je odpojena"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Prostřednictvím aplikace <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Oznámení"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Žádná oznámení"</string> </resources> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index d20fc0cf0d5c..4be2c265b46b 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshottet blev gemt"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tryk for at se dit screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Screenshottet kunne ikke gemmes"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Enheden skal være låst op, før du kan gemme screenshots"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prøv at tage et screenshot igen"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Screenshottet kan ikke gemmes, fordi der er begrænset lagerplads"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Appen eller din organisation tillader ikke, at du tager screenshots"</string> diff --git a/packages/SystemUI/res/values-da/strings_tv.xml b/packages/SystemUI/res/values-da/strings_tv.xml index 84926e0c64f2..fb0bc2d513f9 100644 --- a/packages/SystemUI/res/values-da/strings_tv.xml +++ b/packages/SystemUI/res/values-da/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN er tilsluttet"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN er afbrudt"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifikationer"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ingen notifikationer"</string> </resources> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index dcd6a5351489..038624094333 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot gespeichert"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tippe, um deinen Screenshot anzusehen"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Screenshot konnte nicht gespeichert werden"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Damit Screenshots gespeichert werden können, muss das Gerät entsperrt sein"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Versuche noch einmal, den Screenshot zu erstellen"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Speichern des Screenshots aufgrund von zu wenig Speicher nicht möglich"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Die App oder deine Organisation lässt das Erstellen von Screenshots nicht zu"</string> diff --git a/packages/SystemUI/res/values-de/strings_tv.xml b/packages/SystemUI/res/values-de/strings_tv.xml index 34fc6aadcd41..0345c804f35a 100644 --- a/packages/SystemUI/res/values-de/strings_tv.xml +++ b/packages/SystemUI/res/values-de/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ist verbunden"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ist nicht verbunden"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Über <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Benachrichtigungen"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Keine Benachrichtigungen"</string> </resources> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 197cd17de1f3..298506461338 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Το στιγμιότυπο οθόνης αποθηκεύτηκε"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Πατήστε για να δείτε το στιγμιότυπο οθόνης που δημιουργήσατε"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Μη δυνατή αποθήκευση του στιγμιότυπου οθόνης"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Η συσκευή πρέπει να ξεκλειδωθεί για να αποθηκευτεί το στιγμιότυπο οθόνης."</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Δοκιμάστε να κάνετε ξανά λήψη του στιγμιότυπου οθόνης"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Αδύνατη η αποθήκευση του στιγμιότυπου οθόνης λόγω περιορισμένου αποθηκευτικού χώρου"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Η λήψη στιγμιότυπων οθόνης δεν επιτρέπεται από την εφαρμογή ή τον οργανισμό σας"</string> diff --git a/packages/SystemUI/res/values-el/strings_tv.xml b/packages/SystemUI/res/values-el/strings_tv.xml index 21badf740bf0..cd9277234bd7 100644 --- a/packages/SystemUI/res/values-el/strings_tv.xml +++ b/packages/SystemUI/res/values-el/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Το VPN συνδέθηκε"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Το VPN αποσυνδέθηκε"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Μέσω <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Ειδοποιήσεις"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Δεν υπάρχουν ειδοποιήσεις."</string> </resources> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 85d6276b3885..fbc03967e414 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tap to view your screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organisation"</string> diff --git a/packages/SystemUI/res/values-en-rAU/strings_tv.xml b/packages/SystemUI/res/values-en-rAU/strings_tv.xml index ab370b14a326..3b3e2d6fef48 100644 --- a/packages/SystemUI/res/values-en-rAU/strings_tv.xml +++ b/packages/SystemUI/res/values-en-rAU/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index 5db104ccaa02..a8eed1588a63 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tap to view your screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organisation"</string> diff --git a/packages/SystemUI/res/values-en-rCA/strings_tv.xml b/packages/SystemUI/res/values-en-rCA/strings_tv.xml index ab370b14a326..3b3e2d6fef48 100644 --- a/packages/SystemUI/res/values-en-rCA/strings_tv.xml +++ b/packages/SystemUI/res/values-en-rCA/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 85d6276b3885..fbc03967e414 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tap to view your screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organisation"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings_tv.xml b/packages/SystemUI/res/values-en-rGB/strings_tv.xml index ab370b14a326..3b3e2d6fef48 100644 --- a/packages/SystemUI/res/values-en-rGB/strings_tv.xml +++ b/packages/SystemUI/res/values-en-rGB/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 85d6276b3885..fbc03967e414 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tap to view your screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organisation"</string> diff --git a/packages/SystemUI/res/values-en-rIN/strings_tv.xml b/packages/SystemUI/res/values-en-rIN/strings_tv.xml index ab370b14a326..3b3e2d6fef48 100644 --- a/packages/SystemUI/res/values-en-rIN/strings_tv.xml +++ b/packages/SystemUI/res/values-en-rIN/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index 3719aa7a10e0..47bda8bd0c7f 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tap to view your screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organization"</string> diff --git a/packages/SystemUI/res/values-en-rXC/strings_tv.xml b/packages/SystemUI/res/values-en-rXC/strings_tv.xml index 9fb261012dca..34882b31129d 100644 --- a/packages/SystemUI/res/values-en-rXC/strings_tv.xml +++ b/packages/SystemUI/res/values-en-rXC/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No Notifications"</string> </resources> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index bd649506b6f5..ab23eb6c44e3 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Se guardó la captura de pantalla"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Presiona para ver la captura de pantalla"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"No se pudo guardar la captura de pantalla"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"El dispositivo debe estar desbloqueado para poder guardar la captura de pantalla"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Vuelve a hacer una captura de pantalla"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"No se puede guardar la captura de pantalla debido a que no hay suficiente espacio de almacenamiento"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"La app o tu organización no permiten las capturas de pantalla"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings_tv.xml b/packages/SystemUI/res/values-es-rUS/strings_tv.xml index 7aa99272e9bd..a0a355b8bc7a 100644 --- a/packages/SystemUI/res/values-es-rUS/strings_tv.xml +++ b/packages/SystemUI/res/values-es-rUS/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"La VPN está conectada."</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"La VPN está desconectada"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificaciones"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No hay notificaciones"</string> </resources> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 2ce271896c50..e589ce6ff7a1 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Se ha guardado la captura de pantalla"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Toca para ver la captura de pantalla"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"No se ha podido guardar la captura de pantalla"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"El dispositivo debe desbloquearse para que se pueda guardar la captura de pantalla"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Vuelve a intentar hacer la captura de pantalla"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"No se puede guardar la captura de pantalla porque no hay espacio de almacenamiento suficiente"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"La aplicación o tu organización no permiten realizar capturas de pantalla"</string> diff --git a/packages/SystemUI/res/values-es/strings_tv.xml b/packages/SystemUI/res/values-es/strings_tv.xml index f3bab286fda4..4607ad5d4fcb 100644 --- a/packages/SystemUI/res/values-es/strings_tv.xml +++ b/packages/SystemUI/res/values-es/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"La VPN está conectada"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"La VPN está desconectada"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificaciones"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Sin notificaciones"</string> </resources> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index c11f21ce80ed..cce8d8359b44 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekraanipilt salvestati"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Puudutage ekraanipildi vaatamiseks"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekraanipilti ei õnnestunud salvestada"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Enne ekraanipildi salvestamist tuleb seade avada"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Proovige ekraanipilt uuesti jäädvustada"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Piiratud salvestusruumi tõttu ei saa ekraanipilti salvestada"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Rakendus või teie organisatsioon ei luba ekraanipilte jäädvustada"</string> diff --git a/packages/SystemUI/res/values-et/strings_tv.xml b/packages/SystemUI/res/values-et/strings_tv.xml index c59b5bcc4e29..b7039e394178 100644 --- a/packages/SystemUI/res/values-et/strings_tv.xml +++ b/packages/SystemUI/res/values-et/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN on ühendatud"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN-i ühendus on katkestatud"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"VPN-i <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Märguanded"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Märguandeid pole"</string> </resources> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 835449f9939e..ad64da2c6ae9 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Gorde da pantaila-argazkia"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Sakatu pantaila-argazkia ikusteko"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Ezin izan da gorde pantaila-argazkia"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pantaila-argazkia gordetzeko, gailuak desblokeatuta egon beharko du"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Saiatu berriro pantaila-argazkia ateratzen"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Ezin da gorde pantaila-argazkia ez delako gelditzen tokirik"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikazioak edo erakundeak ez du onartzen pantaila-argazkiak ateratzea"</string> diff --git a/packages/SystemUI/res/values-eu/strings_tv.xml b/packages/SystemUI/res/values-eu/strings_tv.xml index 67cb078b8788..e1c4fcc73ee4 100644 --- a/packages/SystemUI/res/values-eu/strings_tv.xml +++ b/packages/SystemUI/res/values-eu/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN sarera konektatuta dago"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ez dago sarera konektatuta"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> bidez"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Jakinarazpenak"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ez dago jakinarazpenik"</string> </resources> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 55ca0f30c63f..f5f95800eeff 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"نماگرفت ذخیره شد"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"برای مشاهده عکس صفحهنمایشتان ضربه بزنید"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"نماگرفت ذخیره نشد"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"برای ذخیره کردن نماگرفت، قفل دستگاه باید باز باشد"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"دوباره نماگرفت بگیرید"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"به دلیل محدود بودن فضای ذخیرهسازی نمیتوان نماگرفت را ذخیره کرد"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"برنامه یا سازمان شما اجازه نمیدهند نماگرفت بگیرید."</string> diff --git a/packages/SystemUI/res/values-fa/strings_tv.xml b/packages/SystemUI/res/values-fa/strings_tv.xml index 37aaa6408d76..5ad12dfd9d53 100644 --- a/packages/SystemUI/res/values-fa/strings_tv.xml +++ b/packages/SystemUI/res/values-fa/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN متصل است"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN قطع است"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"اعلانها"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"اعلانی ندارید"</string> </resources> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index f5441a28d65e..65db4ce30673 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Kuvakaappaus tallennettu"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Napauta katsoaksesi kuvakaappausta"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Kuvakaappauksen tallennus epäonnistui"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Laitteen lukitus täytyy avata ennen kuin kuvakaappaus voidaan tallentaa"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Yritä ottaa kuvakaappaus uudelleen."</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Kuvakaappauksen tallennus epäonnistui, sillä tallennustilaa ei ole riittävästi"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Sovellus tai organisaatio ei salli kuvakaappauksien tallentamista."</string> diff --git a/packages/SystemUI/res/values-fi/strings_tv.xml b/packages/SystemUI/res/values-fi/strings_tv.xml index 295780b7abdb..61cd5ab16d88 100644 --- a/packages/SystemUI/res/values-fi/strings_tv.xml +++ b/packages/SystemUI/res/values-fi/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN on yhdistetty"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ei ole yhdistettynä"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Palvelun <xliff:g id="VPN_APP">%1$s</xliff:g> kautta"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Ilmoitukset"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ei ilmoituksia"</string> </resources> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 6b598da2826d..0e8e31597f8a 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Capture d\'écran enregistrée"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Touchez pour afficher votre capture d\'écran"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Impossible d\'enregistrer la capture d\'écran"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"L\'appareil doit être déverrouillé avant qu\'une capture d\'écran puisse être enregistrée"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Essayez de faire une autre capture d\'écran"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Impossible d\'enregistrer la capture d\'écran, car l\'espace de stockage est limité"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'application ou votre organisation n\'autorise pas les saisies d\'écran"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml index 696e95980dbf..a667d76a834a 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"RPV connecté"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"RPV déconnecté"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Par <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Aucune notification"</string> </resources> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index b9fa28c53540..28b9bbe90b89 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Capture d\'écran enregistrée"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Appuyez pour voir la capture d\'écran"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Impossible d\'enregistrer la capture d\'écran"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Vous devez déverrouiller l\'appareil pour que la capture d\'écran soit enregistrée"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Essayez de nouveau de faire une capture d\'écran"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Impossible d\'enregistrer la capture d\'écran, car l\'espace de stockage est limité"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Les captures d\'écran ne sont pas autorisées par l\'application ni par votre organisation"</string> diff --git a/packages/SystemUI/res/values-fr/strings_tv.xml b/packages/SystemUI/res/values-fr/strings_tv.xml index f2c5d976dd21..25fab4e5d6d9 100644 --- a/packages/SystemUI/res/values-fr/strings_tv.xml +++ b/packages/SystemUI/res/values-fr/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN connecté"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN déconnecté"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Aucune notification"</string> </resources> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 6cf18b8beed6..808048b7c093 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Gardouse a captura de pantalla"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Toca para ver a captura de pantalla"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Non se puido gardar a captura de pantalla"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Para que se poida gardar a captura de pantalla, o dispositivo debe estar desbloqueado"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Volve tentar crear unha captura de pantalla"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Non se puido gardar a captura de pantalla porque o espazo de almacenamento é limitado"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"A aplicación ou a túa organización non permite realizar capturas de pantalla"</string> diff --git a/packages/SystemUI/res/values-gl/strings_tv.xml b/packages/SystemUI/res/values-gl/strings_tv.xml index 095386be9f71..cd12b94e779d 100644 --- a/packages/SystemUI/res/values-gl/strings_tv.xml +++ b/packages/SystemUI/res/values-gl/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN está conectada"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN está desconectada"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificacións"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Non hai notificacións"</string> </resources> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 35d4e1a36fbe..1ba649a25c30 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"સ્ક્રીનશૉટ સાચવ્યો"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"તમારા સ્ક્રીનશૉટને જોવા માટે ટૅપ કરો"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"સ્ક્રીનશૉટ સાચવી શક્યાં નથી"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"સ્ક્રીનશૉટ સાચવવામાં આવે તે પહેલાં ડિવાઇસને અનલૉક કરવું જરૂરી છે"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ફરીથી સ્ક્રીનશૉટ લેવાનો પ્રયાસ કરો"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"મર્યાદિત સ્ટોરેજ સ્પેસને કારણે સ્ક્રીનશૉટ સાચવી શકાતો નથી"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ઍપ્લિકેશન કે તમારી સંસ્થા દ્વારા સ્ક્રીનશૉટ લેવાની મંજૂરી નથી"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"સામાન્ય સંદેશા"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"સ્ટોરેજ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"હિન્ટ"</string> - <string name="instant_apps" msgid="8337185853050247304">"ઝટપટ ઍપ્લિકેશન"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ચાલી રહી છે"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ઍપ ઇન્સ્ટૉલ કર્યા વિના ખુલી જાય છે."</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ઍપ ઇન્સ્ટૉલ કર્યા વિના ખુલી જાય છે. વધુ જાણવા માટે ટૅપ કરો."</string> diff --git a/packages/SystemUI/res/values-gu/strings_tv.xml b/packages/SystemUI/res/values-gu/strings_tv.xml index 297b6e1a5511..a53e9838b4a0 100644 --- a/packages/SystemUI/res/values-gu/strings_tv.xml +++ b/packages/SystemUI/res/values-gu/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN કનેક્ટ કરેલું છે"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ડિસ્કનેક્ટ કરેલું છે"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> મારફતે"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"નોટિફિકેશન"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"કોઈ નોટિફિકેશન નથી"</string> </resources> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 1d02fd0b5e3a..330ff90b3e2d 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रीनशॉट सेव किया गया"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"अपना स्क्रीनशॉट देखने के लिए टैप करें"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"स्क्रीनशॉट सेव नहीं किया जा सका"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"स्क्रीनशॉट सेव करने के लिए डिवाइस का अनलॉक होना ज़रूरी है"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"स्क्रीनशॉट दोबारा लेने की कोशिश करें"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"मेमोरी कम होने की वजह से स्क्रीनशॉट सेव नहीं किया जा सका"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ऐप्लिकेशन या आपका संगठन स्क्रीनशॉट लेने की अनुमति नहीं देता"</string> @@ -937,7 +938,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"सामान्य संदेश"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"जगह"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"संकेत"</string> - <string name="instant_apps" msgid="8337185853050247304">"झटपट ऐप्लिकेशन"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> चल रहा है"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ऐप्लिकेशन इंस्टॉल किए बिना ही खुल गया है."</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ऐप्लिकेशन इंस्टॉल किए बिना ही खुल गया है. ज़्यादा जानने के लिए टैप करें."</string> diff --git a/packages/SystemUI/res/values-hi/strings_tv.xml b/packages/SystemUI/res/values-hi/strings_tv.xml index d2ce7a9a23f8..fedaae3f4710 100644 --- a/packages/SystemUI/res/values-hi/strings_tv.xml +++ b/packages/SystemUI/res/values-hi/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"वीपीएन कनेक्ट हो गया है"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"वीपीएन डिसकनेक्ट हो गया है"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> के ज़रिए"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"सूचनाएं"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"कोई सूचना नहीं है"</string> </resources> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 9c4939cd5383..6879259e6be7 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimka zaslona spremljena"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Dodirnite da biste vidjeli snimku zaslona"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Snimka zaslona nije spremljena"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Uređaj mora biti otključan da bi se snimka zaslona mogla spremiti"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Pokušajte ponovo napraviti snimku zaslona"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Zaslon nije snimljen zbog ograničenog prostora za pohranu"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikacija ili vaša organizacija ne dopuštaju snimanje zaslona"</string> diff --git a/packages/SystemUI/res/values-hr/strings_tv.xml b/packages/SystemUI/res/values-hr/strings_tv.xml index ee29a6c1ee70..3bfdf7038018 100644 --- a/packages/SystemUI/res/values-hr/strings_tv.xml +++ b/packages/SystemUI/res/values-hr/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN je spojen"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN je isključen"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Putem mreže <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Obavijesti"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nema obavijesti"</string> </resources> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 2feb1b258370..90f42cbe0350 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"A képernyőkép mentése sikerült"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Koppintson a képernyőkép megtekintéséhez"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Nem sikerült a képernyőkép mentése"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Az eszközt fel kell oldani a képernyőkép mentése előtt"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Próbálja meg újra elkészíteni a képernyőképet"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Nem menthet képernyőképet, mert kevés a tárhely"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Az alkalmazás vagy az Ön szervezete nem engedélyezi képernyőkép készítését"</string> diff --git a/packages/SystemUI/res/values-hu/strings_tv.xml b/packages/SystemUI/res/values-hu/strings_tv.xml index cbbebb0710d6..78d6099b74a0 100644 --- a/packages/SystemUI/res/values-hu/strings_tv.xml +++ b/packages/SystemUI/res/values-hu/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN-kapcsolat létrejött"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN-kapcsolat megszakadt"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A következő szolgáltatás használatával: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Értesítések"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nincs értesítés"</string> </resources> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index 0258e44ee64b..aaa27948c494 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Սքրինշոթը պահվեց"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Հպեք՝ սքրինշոթը տեսնելու համար"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Չհաջողվեց պահել սքրինշոթը"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Սքրինշոթը պահելու համար ապակողպեք սարքը։"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Փորձեք նորից"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Չհաջողվեց պահել սքրինշոթը անբավարար հիշողության պատճառով"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Հավելվածը կամ ձեր կազմակերպությունը չի թույլատրում սքրինշոթի ստացումը"</string> diff --git a/packages/SystemUI/res/values-hy/strings_tv.xml b/packages/SystemUI/res/values-hy/strings_tv.xml index 58c514931cc6..cf4eb90faff2 100644 --- a/packages/SystemUI/res/values-hy/strings_tv.xml +++ b/packages/SystemUI/res/values-hy/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN-ը միացված է"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN-ն անջատված է"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-ի միջոցով"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Ծանուցումներ"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ծանուցումներ չկան"</string> </resources> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index bea37ae65dba..ff5d4ed0fdf5 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot disimpan"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Ketuk untuk melihat screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Tidak dapat menyimpan screenshot"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Perangkat harus dibuka kuncinya agar screenshot dapat disimpan"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Coba ambil screenshot lagi"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Tidak dapat menyimpan screenshot karena ruang penyimpanan terbatas"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Mengambil screenshot tidak diizinkan oleh aplikasi atau organisasi"</string> diff --git a/packages/SystemUI/res/values-in/strings_tv.xml b/packages/SystemUI/res/values-in/strings_tv.xml index bdd6742c39cf..3b446ad23ed5 100644 --- a/packages/SystemUI/res/values-in/strings_tv.xml +++ b/packages/SystemUI/res/values-in/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN tersambung"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN terputus"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Melalui <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifikasi"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Tidak Ada Notifikasi"</string> </resources> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 7c7902faad2e..20231b4223c5 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Skjámynd vistuð"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Ýttu til skoða skjámyndina"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekki var hægt að vista skjámynd"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Taka verður tækið úr lás áður en hægt er að vista skjámynd"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prófaðu að taka skjámynd aftur"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Ekki tókst að vista skjámynd vegna takmarkaðs geymslupláss"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Forritið eða fyrirtækið þitt leyfir ekki skjámyndatöku"</string> diff --git a/packages/SystemUI/res/values-is/strings_tv.xml b/packages/SystemUI/res/values-is/strings_tv.xml index 88a43159c064..7c23e62dfdcf 100644 --- a/packages/SystemUI/res/values-is/strings_tv.xml +++ b/packages/SystemUI/res/values-is/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN er tengt"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN er ekki tengt"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Í gegnum <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Tilkynningar"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Engar tilkynningar"</string> </resources> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 026b5a98a682..a7952ba45c82 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot salvato"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tocca per visualizzare lo screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Impossibile salvare lo screenshot"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"È necessario sbloccare il dispositivo per poter salvare lo screenshot"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Riprova ad acquisire lo screenshot"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Impossibile salvare lo screenshot a causa dello spazio di archiviazione limitato"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'acquisizione di screenshot non è consentita dall\'app o dall\'organizzazione"</string> diff --git a/packages/SystemUI/res/values-it/strings_tv.xml b/packages/SystemUI/res/values-it/strings_tv.xml index 97badc1e2180..57931b02d58a 100644 --- a/packages/SystemUI/res/values-it/strings_tv.xml +++ b/packages/SystemUI/res/values-it/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN connessa"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN disconnessa"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Tramite <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifiche"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nessuna notifica"</string> </resources> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index b4df62b5207e..cd07d770d6b5 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"צילום המסך נשמר"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"אפשר להקיש כדי להציג את צילום המסך"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"לא ניתן היה לשמור צילום מסך"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"כדי שצילום המסך יישמר, צריך לבטל את הנעילה של המכשיר"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"יש לנסות שוב לבצע צילום מסך"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"לא היה מספיק מקום לשמור את צילום המסך"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"האפליקציה או הארגון שלך אינם מתירים ליצור צילומי מסך"</string> diff --git a/packages/SystemUI/res/values-iw/strings_tv.xml b/packages/SystemUI/res/values-iw/strings_tv.xml index 45d744ab8a57..7483116177f6 100644 --- a/packages/SystemUI/res/values-iw/strings_tv.xml +++ b/packages/SystemUI/res/values-iw/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN מחובר"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN מנותק"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"באמצעות <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"התראות"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"אין התראות"</string> </resources> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index be6f491b8356..1b30a925a330 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"スクリーンショットを保存しました"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"タップしてスクリーンショットを表示します"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"スクリーンショット保存エラー"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"スクリーンショットを保存するには、デバイスのロックを解除する必要があります"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"スクリーンショットを撮り直してください"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"空き容量が足りないため、スクリーンショットを保存できません"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"スクリーンショットの作成はアプリまたは組織で許可されていません"</string> diff --git a/packages/SystemUI/res/values-ja/strings_tv.xml b/packages/SystemUI/res/values-ja/strings_tv.xml index 9d7a36a20f76..7f676b5acbe2 100644 --- a/packages/SystemUI/res/values-ja/strings_tv.xml +++ b/packages/SystemUI/res/values-ja/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN に接続しました"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN に接続していません"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> 経由"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"通知はありません"</string> </resources> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 6fdb8b89918f..f128ddeefb2c 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"ეკრანის ანაბეჭდი შენახულია"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"შეეხეთ ეკრანის ანაბეჭდის სანახავად"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"ეკრანის ანაბეჭდის შენახვა ვერ მოხერხდა"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"მოწყობილობა უნდა განიბლოკოს ეკრანის ანაბეჭდის შენახვა რომ შეძლოთ"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ხელახლა ცადეთ ეკრანის ანაბეჭდის გაკეთება"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ეკრანის ანაბეჭდის შენახვა ვერ მოხერხდა შეზღუდული მეხსიერების გამო"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ეკრანის ანაბეჭდების შექმნა არ არის ნებადართული აპის ან თქვენი ორგანიზაციის მიერ"</string> diff --git a/packages/SystemUI/res/values-ka/strings_tv.xml b/packages/SystemUI/res/values-ka/strings_tv.xml index 0dc1e10cdc9f..081978125ee3 100644 --- a/packages/SystemUI/res/values-ka/strings_tv.xml +++ b/packages/SystemUI/res/values-ka/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN დაკავშირებულია"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN გათიშულია"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-ის მიერ"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"შეტყობინებები"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"შეტყობინებები არ არის"</string> </resources> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index df86e8a4774c..b9c54cc81a2d 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сақталды"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Скриншотты көру үшін түртіңіз"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Скриншот сақталмады"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Скриншот сақталуы үшін, құрылғы құлпын ашу керек."</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Қайта скриншот жасап көріңіз"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Жадтағы шектеулі бос орынға байланысты скриншот сақталмайды"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Қолданба немесе ұйым скриншоттар түсіруге рұқсат етпейді"</string> diff --git a/packages/SystemUI/res/values-kk/strings_tv.xml b/packages/SystemUI/res/values-kk/strings_tv.xml index cc15978b5076..768e3ac19316 100644 --- a/packages/SystemUI/res/values-kk/strings_tv.xml +++ b/packages/SystemUI/res/values-kk/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN қосылған"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ажыратылған"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> арқылы жалғанған"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Хабарландырулар"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Хабарландырулар жоқ"</string> </resources> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index e559c1951c50..d293c0d7c02e 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"បានរក្សាទុករូបថតអេក្រង់"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"ចុចដើម្បីមើលរូបថតអេក្រង់របស់អ្នក"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"មិនអាចរក្សាទុករូបថតអេក្រង់បានទេ"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ត្រូវតែដោះសោឧបករណ៍ជាមុនសិន ទើបអាចរក្សាទុករូបថតអេក្រង់បាន"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"សាកល្បងថតរូបថតអេក្រង់ម្តងទៀត"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"មិនអាចរក្សាទុករូបថតអេក្រង់បានទេ ដោយសារទំហំផ្ទុកមានកម្រិតទាប"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ការថតរូបអេក្រង់មិនត្រូវបានអនុញ្ញាតដោយកម្មវិធីនេះ ឬស្ថាប័នរបស់អ្នក"</string> diff --git a/packages/SystemUI/res/values-km/strings_tv.xml b/packages/SystemUI/res/values-km/strings_tv.xml index f415a66658de..0dec2d65e5bf 100644 --- a/packages/SystemUI/res/values-km/strings_tv.xml +++ b/packages/SystemUI/res/values-km/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ត្រូវបានភ្ជាប់"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ត្រូវបានផ្ដាច់"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"តាមរយៈ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"ការជូនដំណឹង"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"គ្មានការជូនដំណឹងទេ"</string> </resources> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index f1210804841e..a906a39288c6 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಅನ್ನು ಉಳಿಸಲಾಗಿದೆ"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ಶಾಟ್ ವೀಕ್ಷಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಅನ್ನು ಉಳಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಉಳಿಸುವ ಮೊದಲು ಸಾಧನವನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಬೇಕು"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಅನ್ನು ಪುನಃ ತೆಗೆದುಕೊಳ್ಳಲು ಪ್ರಯತ್ನಿಸಿ"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ಪರಿಮಿತ ಸಂಗ್ರಹಣೆ ಸ್ಥಳದ ಕಾರಣದಿಂದಾಗಿ ಸ್ಕ್ರೀನ್ಶಾಟ್ ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ಅಪ್ಲಿಕೇಶನ್ ಅಥವಾ ಸಂಸ್ಥೆಯು ಸ್ಕ್ರೀನ್ಶಾಟ್ಗಳನ್ನು ತೆಗೆಯುವುದನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"ಸಾಮಾನ್ಯ ಸಂದೇಶಗಳು"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"ಸಂಗ್ರಹಣೆ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"ಸುಳಿವುಗಳು"</string> - <string name="instant_apps" msgid="8337185853050247304">"ಇನ್ಸ್ಟಂಟ್ ಆ್ಯಪ್ಗಳು"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ರನ್ ಆಗುತ್ತಿದೆ"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ಇನ್ಸ್ಟಾಲ್ ಮಾಡದೆ ಆ್ಯಪ್ ತೆರೆಯಲಾಗಿದೆ."</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ಇನ್ಸ್ಟಾಲ್ ಮಾಡದೆ ಆ್ಯಪ್ ತೆರೆಯಲಾಗಿದೆ. ಇನ್ನಷ್ಟು ತಿಳಿಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> diff --git a/packages/SystemUI/res/values-kn/strings_tv.xml b/packages/SystemUI/res/values-kn/strings_tv.xml index a9359639f573..ef10e3a2a664 100644 --- a/packages/SystemUI/res/values-kn/strings_tv.xml +++ b/packages/SystemUI/res/values-kn/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ಕನೆಕ್ಷನ್ ಕಡಿತಗೊಂಡಿದೆ"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ಮೂಲಕ"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"ಅಧಿಸೂಚನೆಗಳು"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ಯಾವುದೇ ಅಧಿಸೂಚನೆಗಳಿಲ್ಲ"</string> </resources> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 6db40c192aea..adedb88a59c6 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"스크린샷 저장됨"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"스크린샷을 확인하려면 탭하세요"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"스크린샷을 저장할 수 없음"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"스크린샷을 저장하려면 기기를 잠금 해제해야 합니다."</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"스크린샷을 다시 찍어 보세요."</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"저장용량이 부족하여 스크린샷을 저장할 수 없습니다"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"앱이나 조직에서 스크린샷 촬영을 허용하지 않습니다."</string> diff --git a/packages/SystemUI/res/values-ko/strings_tv.xml b/packages/SystemUI/res/values-ko/strings_tv.xml index 8c3a8ea65de2..f9c723a3b33b 100644 --- a/packages/SystemUI/res/values-ko/strings_tv.xml +++ b/packages/SystemUI/res/values-ko/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN에 연결됨"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN 연결이 해제됨"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>에 연결됨"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"알림"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"알림 없음"</string> </resources> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 8a06ed67e2f8..92b98fb80939 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сакталды"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Скриншотуңузду көрүү үчүн таптап коюңуз"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Скриншот сакталган жок"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Скриншотту сактоо үчүн түзмөктүн кулпусун ачуу керек"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Скриншотту кайра тартып көрүңүз"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Сактагычта бош орун аз болгондуктан, скриншот сакталбай жатат"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Скриншот тартууга колдонмо же ишканаңыз тыюу салган."</string> diff --git a/packages/SystemUI/res/values-ky/strings_tv.xml b/packages/SystemUI/res/values-ky/strings_tv.xml index 3be657c78b2c..1dba865803d2 100644 --- a/packages/SystemUI/res/values-ky/strings_tv.xml +++ b/packages/SystemUI/res/values-ky/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN туташтырылды"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ажыратылды"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> аркылуу"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Билдирмелер"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Билдирме жок"</string> </resources> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index b92c2c17e7f9..aa3bc8829f30 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"ບັນທຶກຮູບໜ້າຈໍໄວ້ແລ້ວ"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"ແຕະເພື່ອເບິ່ງພາບຖ່າຍໜ້າຈໍຂອງທ່ານ"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"ບໍ່ສາມາດບັນທຶກຮູບໜ້າຈໍໄດ້"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ຈະຕ້ອງປົດລັອກອຸປະກອນກ່ອນບັນທຶກຮູບໜ້າຈໍ"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ກະລຸນາລອງຖ່າຍຮູບໜ້າຈໍອີກຄັ້ງ"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້ເນື່ອງຈາກພື້ນທີ່ຈັດເກັບຂໍ້ມູນມີຈຳກັດ"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ແອັບ ຫຼື ອົງກອນຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ຖ່າຍຮູບໜ້າຈໍ"</string> diff --git a/packages/SystemUI/res/values-lo/strings_tv.xml b/packages/SystemUI/res/values-lo/strings_tv.xml index 445e56229bf9..a45fb45cc76f 100644 --- a/packages/SystemUI/res/values-lo/strings_tv.xml +++ b/packages/SystemUI/res/values-lo/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"ເຊື່ອມຕໍ່ VPN ແລ້ວ"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"ຕັດການເຊື່ອມຕໍ່ VPN ແລ້ວ"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ຜ່ານ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"ການແຈ້ງເຕືອນ"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ບໍ່ມີການແຈ້ງເຕືອນ"</string> </resources> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index cac9cf1dbc92..c40c5c9c269d 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekrano kopija išsaugota"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Palieskite, kad peržiūrėtumėte ekrano kopiją"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekrano kopijos išsaugoti nepavyko"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Įrenginys turi būti atrakintas, kad būtų galima išsaugoti ekrano kopiją"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Pabandykite padaryti ekrano kopiją dar kartą"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Negalima išsaugoti ekrano kopijos dėl ribotos saugyklos vietos"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Jūsų organizacijoje arba naudojant šią programą neleidžiama daryti ekrano kopijų"</string> diff --git a/packages/SystemUI/res/values-lt/strings_tv.xml b/packages/SystemUI/res/values-lt/strings_tv.xml index c749cdfbe22c..8c329f961b5c 100644 --- a/packages/SystemUI/res/values-lt/strings_tv.xml +++ b/packages/SystemUI/res/values-lt/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN prijungtas"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN atjungtas"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Per „<xliff:g id="VPN_APP">%1$s</xliff:g>“"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Pranešimai"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nėra jokių pranešimų"</string> </resources> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index da8adb46000b..85b272a575c3 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekrānuzņēmums saglabāts"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Pieskarieties, lai skatītu ekrānuzņēmumu."</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekrānuzņēmumu neizdevās saglabāt."</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Lai varētu saglabāt ekrānuzņēmumu, ierīcei ir jābūt atbloķētai."</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Mēģiniet izveidot jaunu ekrānuzņēmumu."</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Nevar saglabāt ekrānuzņēmumu, jo krātuvē nepietiek vietas."</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Lietotne vai jūsu organizācija neatļauj veikt ekrānuzņēmumus."</string> diff --git a/packages/SystemUI/res/values-lv/strings_tv.xml b/packages/SystemUI/res/values-lv/strings_tv.xml index f752439165b4..758d28cddc82 100644 --- a/packages/SystemUI/res/values-lv/strings_tv.xml +++ b/packages/SystemUI/res/values-lv/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Savienojums ar VPN ir izveidots."</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Savienojums ar VPN ir pārtraukts."</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Izmantojot: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Paziņojumi"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nav paziņojumu"</string> </resources> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 2416dbde4408..bbcf93c7d18e 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Сликата од екранот е зачувана"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Допрете за да ја видите сликата од екранот"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Не може да се зачува слика од екранот"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Уредот мора да биде отклучен за да може да се зачува слика од екранот"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Повторно обидете се да направите слика од екранот"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Сликата од екранот не може да се зачува поради ограничена меморија"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Апликацијата или вашата организација не дозволува снимање слики од екранот"</string> diff --git a/packages/SystemUI/res/values-mk/strings_tv.xml b/packages/SystemUI/res/values-mk/strings_tv.xml index 947281341e30..0dfbd79de131 100644 --- a/packages/SystemUI/res/values-mk/strings_tv.xml +++ b/packages/SystemUI/res/values-mk/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN е поврзана"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN е исклучена"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Преку <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Известувања"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Нема известувања"</string> </resources> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 4d77fcd4054f..b4db453df156 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"സ്ക്രീൻഷോട്ട് സംരക്ഷിച്ചു"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"സ്ക്രീൻഷോട്ട് കാണാൻ ടാപ്പ് ചെയ്യുക"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കാനായില്ല"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നതിന് മുമ്പ് ഉപകരണം അൺലോക്ക് ചെയ്തിരിക്കണം"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"സ്ക്രീൻഷോട്ട് എടുക്കാൻ വീണ്ടും ശ്രമിക്കുക"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"സ്റ്റോറേജ് ഇടം പരിമിതമായതിനാൽ സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കാനാകുന്നില്ല"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"സ്ക്രീൻഷോട്ടുകൾ എടുക്കുന്നത് ആപ്പോ നിങ്ങളുടെ സ്ഥാപനമോ അനുവദിക്കുന്നില്ല"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"പൊതുവായ സന്ദേശങ്ങൾ"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"സ്റ്റോറേജ്"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"സൂചനകൾ"</string> - <string name="instant_apps" msgid="8337185853050247304">"ഇൻസ്റ്റന്റ് ആപ്പ്"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> റണ് ചെയ്യുന്നു"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ഇൻസ്റ്റാൾ ചെയ്യാതെ ആപ്പ് തുറന്നു."</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ഇൻസ്റ്റാൾ ചെയ്യാതെ ആപ്പ് തുറന്നു. കൂടുതലറിയാൻ ടാപ്പ് ചെയ്യുക."</string> diff --git a/packages/SystemUI/res/values-ml/strings_tv.xml b/packages/SystemUI/res/values-ml/strings_tv.xml index fe7979665edd..70cced8e810c 100644 --- a/packages/SystemUI/res/values-ml/strings_tv.xml +++ b/packages/SystemUI/res/values-ml/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN കണക്റ്റ് ചെയ്തു"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN വിച്ഛേദിച്ചു"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> വഴി"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"അറിയിപ്പുകൾ"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"അറിയിപ്പുകൾ ഒന്നുമില്ല"</string> </resources> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 0d605c11cd1d..6a96a5019c36 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Дэлгэцээс дарсан зургийг хадгалсан"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Дэлгэцээс дарсан зургийг харах бол товшино уу"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Дэлгэцээс дарсан зургийг хадгалж чадсангүй"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Дэлгэцийн агшныг хадгалах боломжтой болохоос өмнө төхөөрөмжийн түгжээг тайлах ёстой"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Дэлгэцийн зургийг дахин дарж үзнэ үү"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Сангийн багтаамж бага байгаа тул дэлгэцээс дарсан зургийг хадгалах боломжгүй байна"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Таны апп, байгууллагад дэлгэцийн зураг авахыг зөвшөөрдөггүй"</string> diff --git a/packages/SystemUI/res/values-mn/strings_tv.xml b/packages/SystemUI/res/values-mn/strings_tv.xml index 9ec66d1bf26f..221d8ae058f9 100644 --- a/packages/SystemUI/res/values-mn/strings_tv.xml +++ b/packages/SystemUI/res/values-mn/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN холбогдсон"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN салсан"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-р"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Мэдэгдэл"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Мэдэгдэл байхгүй байна"</string> </resources> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index a487a6377ed5..a667ab7cd52f 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रीनशॉट सेव्ह केला"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"तुमचा स्क्रीनशॉट पाहण्यासाठी टॅप करा"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"स्क्रीनशॉट सेव्ह करू शकलो नाही"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"स्क्रीनशॉट सेव्ह करण्याआधी डिव्हाइस अनलॉक करणे आवश्यक आहे"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"स्क्रीनशॉट पुन्हा घेण्याचा प्रयत्न करा"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"मर्यादित स्टोरेज जागेमुळे स्क्रीनशॉट सेव्ह करू शकत नाही"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"अॅप किंवा आपल्या संस्थेद्वारे स्क्रीनशॉट घेण्याची अनुमती नाही"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"सर्वसाधारण मेसेज"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"स्टोरेज"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"सूचना"</string> - <string name="instant_apps" msgid="8337185853050247304">"इन्सटंट अॅप्स"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> रन होत आहे"</string> <string name="instant_apps_message" msgid="6112428971833011754">"इंस्टॉल केल्याशिवाय अॅप उघडले."</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"इंस्टॉल केल्याशिवाय अॅप उघडले. अधिक जाणून घेण्यासाठी टॅप करा."</string> diff --git a/packages/SystemUI/res/values-mr/strings_tv.xml b/packages/SystemUI/res/values-mr/strings_tv.xml index 791a4fd0c802..ac0cad132fd0 100644 --- a/packages/SystemUI/res/values-mr/strings_tv.xml +++ b/packages/SystemUI/res/values-mr/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN कनेक्ट केले"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN डिस्कनेक्ट केले"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> द्वारे"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"सूचना"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"सूचना नाहीत"</string> </resources> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 8f426ede9b75..86565902910e 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Tangkapan skrin disimpan"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Ketik untuk melihat tangkapan skrin anda"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Tidak dapat menyimpan tangkapan skrin"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Peranti mesti dibuka kunci sebelum tangkapan skrin dapat disimpan"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Cuba ambil tangkapan skrin sekali lagi"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Tidak dapat menyimpan tangkapan skrin kerana ruang storan terhad"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Pengambilan tangkapan skrin tidak dibenarkan oleh apl atau organisasi anda"</string> diff --git a/packages/SystemUI/res/values-ms/strings_tv.xml b/packages/SystemUI/res/values-ms/strings_tv.xml index 65c8068d0505..46e345efc16b 100644 --- a/packages/SystemUI/res/values-ms/strings_tv.xml +++ b/packages/SystemUI/res/values-ms/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN telah disambungkan"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN diputuskan sambungan"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Melalui <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Pemberitahuan"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Tiada Pemberitahuan"</string> </resources> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 9d8ffc93fae0..5b5531d06b2b 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းပြီးပါပြီ"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"ဖန်သားပြင်ဓာတ်ပုံကို ကြည့်ရန် တို့ပါ"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"မျက်နှာပြင်ပုံကို သိမ်း၍မရပါ"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ဖန်သားပြင်ဓာတ်ပုံကို မသိမ်းမီ စက်ပစ္စည်းကို လော့ခ်ဖွင့်ထားရမည်"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"မျက်နှာပြင်ပုံကို ထပ်ရိုက်ကြည့်ပါ"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"သိုလှောင်ခန်းနေရာ အကန့်အသတ်ရှိသောကြောင့် ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းဆည်း၍မရပါ"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ဖန်သားပြင်ဓာတ်ပုံရိုက်ကူးခြင်းကို ဤအက်ပ် သို့မဟုတ် သင်၏အဖွဲ့အစည်းက ခွင့်မပြုပါ"</string> diff --git a/packages/SystemUI/res/values-my/strings_tv.xml b/packages/SystemUI/res/values-my/strings_tv.xml index c07b9a596b06..268c5540ef5b 100644 --- a/packages/SystemUI/res/values-my/strings_tv.xml +++ b/packages/SystemUI/res/values-my/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ချိတ်ဆက်ထားသည်"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ချိတ်ဆက်မှုမရှိပါ"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> မှတစ်ဆင့်"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"အကြောင်းကြားချက်များ"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"အကြောင်းကြားချက်များ မရှိပါ"</string> </resources> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 1d30e2bf89bd..6b0568df9f35 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Skjermdumpen er lagret"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Trykk for å se skjermdumpen"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Kunne ikke lagre skjermdump"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Enheten må være låst opp før skjermdumpen kan lagres"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prøv å ta skjermdump på nytt"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Kan ikke lagre skjermdumpen på grunn av begrenset lagringsplass"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Appen eller organisasjonen din tillater ikke at du tar skjermdumper"</string> diff --git a/packages/SystemUI/res/values-nb/strings_tv.xml b/packages/SystemUI/res/values-nb/strings_tv.xml index 6346519c3823..c5767dd94c03 100644 --- a/packages/SystemUI/res/values-nb/strings_tv.xml +++ b/packages/SystemUI/res/values-nb/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN er tilkoblet"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN er frakoblet"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Varsler"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ingen varsler"</string> </resources> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index 881be66c00c2..f72808f61348 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रिनसट सुरक्षित गरियो"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"आफ्नो स्क्रिनसट हेर्न ट्याप गर्नुहोस्"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"स्क्रिनसट सुरक्षित गर्न सकिएन"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"यन्त्र अनलक गरेपछि मात्र स्क्रिनसट सुरक्षित गर्न सकिन्छ"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"स्क्रिनसट फेरि लिएर हेर्नुहोस्"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"भण्डारण ठाउँ सीमित भएका कारण स्क्रिनसट सुरक्षित गर्न सकिएन"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"उक्त एप वा तपाईंको संगठनले स्क्रिनसटहरू लिन दिँदैन"</string> diff --git a/packages/SystemUI/res/values-ne/strings_tv.xml b/packages/SystemUI/res/values-ne/strings_tv.xml index 00cc10aadf8a..925f7b76c12e 100644 --- a/packages/SystemUI/res/values-ne/strings_tv.xml +++ b/packages/SystemUI/res/values-ne/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN कनेक्ट गरिएको छ"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN डिस्कनेक्ट गरिएको छ"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> मार्फत"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"सूचनाहरू"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"कुनै पनि सूचना छैन"</string> </resources> diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml index 8cc747bf04d6..d0aef6fe2e65 100644 --- a/packages/SystemUI/res/values-night/colors.xml +++ b/packages/SystemUI/res/values-night/colors.xml @@ -44,11 +44,8 @@ <color name="notification_section_clear_all_btn_color">@color/GM2_grey_500</color> <color name="notification_channel_dialog_separator">@color/GM2_grey_700</color> - <!-- The color of the background in the top part of QSCustomizer --> - <color name="qs_customize_background">@color/GM2_grey_900</color> - <!-- The color of the background in the bottom part of QSCustomizer --> - <color name="qs_customize_decoration">@color/GM2_grey_800</color> + <color name="qs_customize_decoration">@color/GM2_grey_900</color> <!-- The color of the background in the separated list of the Global Actions menu --> <color name="global_actions_separated_background">@color/GM2_grey_900</color> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 6bed66bb171e..aa738c495754 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot opgeslagen"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tik om je screenshot te bekijken"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Kan screenshot niet opslaan"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Je moet het apparaat ontgrendelen voordat het screenshot kan worden opgeslagen"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Probeer opnieuw een screenshot te maken"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Kan screenshot niet opslaan vanwege beperkte opslagruimte"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Het maken van screenshots wordt niet toegestaan door de app of je organisatie"</string> diff --git a/packages/SystemUI/res/values-nl/strings_tv.xml b/packages/SystemUI/res/values-nl/strings_tv.xml index 11f70b4dfe94..22d3b8806bbd 100644 --- a/packages/SystemUI/res/values-nl/strings_tv.xml +++ b/packages/SystemUI/res/values-nl/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Verbinding met VPN"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Geen verbinding met VPN"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Meldingen"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Geen meldingen"</string> </resources> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index a809da3d2fe2..7e3406746c5e 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"ସ୍କ୍ରୀନଶଟ୍ ସେଭ୍ ହୋଇଛି"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"ସ୍କ୍ରୀନଶଟ୍ ଦେଖିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"ସ୍କ୍ରୀନ୍ଶଟ୍ ସେଭ୍ କରିହେବ ନାହିଁ"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ସ୍କ୍ରିନସଟ୍ ସେଭ୍ କରିବା ପୂର୍ବରୁ ଡିଭାଇସକୁ ଅନଲକ୍ କରାଯିବା ଆବଶ୍ୟକ"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ପୁଣିଥରେ ସ୍କ୍ରୀନ୍ଶଟ୍ ନେବାକୁ ଚେଷ୍ଟା କରନ୍ତୁ"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ସୀମିତ ଷ୍ଟୋରେଜ୍ ସ୍ପେସ୍ ହେତୁ ସ୍କ୍ରୀନଶଟ୍ ସେଭ୍ ହୋଇପାରିବ ନାହିଁ"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ଆପ୍ କିମ୍ବା ସଂସ୍ଥା ଦ୍ୱାରା ସ୍କ୍ରୀନଶଟ୍ ନେବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"ସାଧାରଣ ମେସେଜ୍"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"ଷ୍ଟୋରେଜ୍"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"ହିଣ୍ଟ"</string> - <string name="instant_apps" msgid="8337185853050247304">"ଇନଷ୍ଟାଣ୍ଟ ଆପ୍"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ଚାଲୁଛି"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ଇନ୍ଷ୍ଟଲ୍ ନହୋଇ ଆପ୍ ଖୋଲିଛି।"</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ଇନ୍ଷ୍ଟଲ୍ ନହୋଇ ଆପ୍ ଖୋଲିଛି। ଅଧିକ ଜାଣିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string> diff --git a/packages/SystemUI/res/values-or/strings_tv.xml b/packages/SystemUI/res/values-or/strings_tv.xml index f436babfa20a..707c49e183c7 100644 --- a/packages/SystemUI/res/values-or/strings_tv.xml +++ b/packages/SystemUI/res/values-or/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ସଂଯୋଗ କରାଯାଇଛି"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ବିଚ୍ଛିନ୍ନ କରାଯାଇଛି"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ମାଧ୍ୟମରେ"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"କୌଣସି ବିଜ୍ଞପ୍ତି ନାହିଁ"</string> </resources> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index d9a68281eb73..ca4b6ad2cffb 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"ਆਪਣਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਨੂੰ ਰੱਖਿਅਤ ਕੀਤੇ ਜਾਣ ਤੋਂ ਪਹਿਲਾਂ ਡੀਵਾਈਸ ਨੂੰ ਅਣਲਾਕ ਕੀਤਾ ਹੋਣਾ ਲਾਜ਼ਮੀ ਹੈ"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੁਬਾਰਾ ਲੈ ਕੇ ਦੇਖੋ"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ਸੀਮਿਤ ਸਟੋਰੇਜ ਹੋਣ ਕਾਰਨ ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈਣ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਹੈ"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"ਆਮ ਸੁਨੇਹੇ"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"ਸਟੋਰੇਜ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"ਸੰਕੇਤ"</string> - <string name="instant_apps" msgid="8337185853050247304">"ਤਤਕਾਲ ਐਪਾਂ"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ਚੱਲ ਰਹੀ ਹੈ"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ਸਥਾਪਤ ਕੀਤੇ ਬਿਨਾਂ ਐਪ ਖੋਲ੍ਹੀ ਗਈ।"</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ਸਥਾਪਤ ਕੀਤੇ ਬਿਨਾਂ ਐਪ ਖੋਲ੍ਹੀ ਗਈ। ਹੋਰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> diff --git a/packages/SystemUI/res/values-pa/strings_tv.xml b/packages/SystemUI/res/values-pa/strings_tv.xml index d10daa85da5a..c0761942b2ee 100644 --- a/packages/SystemUI/res/values-pa/strings_tv.xml +++ b/packages/SystemUI/res/values-pa/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ਕਨੈਕਟ ਹੈ"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ਡਿਸਕਨੈਕਟ ਹੈ"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ਰਾਹੀਂ"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"ਸੂਚਨਾਵਾਂ"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ਕੋਈ ਸੂਚਨਾ ਨਹੀਂ"</string> </resources> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 3e944b5f7317..142a507dfd58 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Zrzut ekranu został zapisany"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Kliknij, by zobaczyć zrzut ekranu"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Nie udało się zapisać zrzutu ekranu"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Przed zapisaniem zrzutu ekranu musisz odblokować urządzenie"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Spróbuj jeszcze raz wykonać zrzut ekranu"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Nie można zapisać zrzutu ekranu, bo brakuje miejsca w pamięci"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Nie możesz wykonać zrzutu ekranu, bo nie zezwala na to aplikacja lub Twoja organizacja."</string> diff --git a/packages/SystemUI/res/values-pl/strings_tv.xml b/packages/SystemUI/res/values-pl/strings_tv.xml index d83391e01b57..e63aadee9d65 100644 --- a/packages/SystemUI/res/values-pl/strings_tv.xml +++ b/packages/SystemUI/res/values-pl/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Połączono z VPN"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Rozłączono z VPN"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Przez: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Powiadomienia"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Brak powiadomień"</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index d058eddbcf36..82139f525c44 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de tela salva"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Toque para ver sua captura de tela"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Falha ao salvar a captura de tela"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Para que a captura de tela seja salva, o dispositivo precisa ser desbloqueado"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Tente fazer a captura de tela novamente"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Não é possível salvar a captura de tela, porque não há espaço suficiente"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"O app ou a organização não permitem capturas de tela"</string> diff --git a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml index 49b923d076b7..2ea81526feed 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN está conectada"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN está desconectada"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificações"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nenhuma notificação"</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index dcaf46027b2c..61cc9137a9db 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de ecrã guardada"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Toque para ver a captura de ecrã."</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Não foi possível guardar a captura de ecrã"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"É necessário desbloquear o dispositivo para guardar a captura de ecrã"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Experimente voltar a efetuar a captura de ecrã."</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Não é possível guardar a captura de ecrã devido a espaço de armazenamento limitado."</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"A app ou a sua entidade não permitem tirar capturas de ecrã"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml index a36a1a92d882..8ce3e307c659 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN está ligada"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN está desligada"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Através de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificações"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Sem notificações"</string> </resources> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index d058eddbcf36..82139f525c44 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de tela salva"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Toque para ver sua captura de tela"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Falha ao salvar a captura de tela"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Para que a captura de tela seja salva, o dispositivo precisa ser desbloqueado"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Tente fazer a captura de tela novamente"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Não é possível salvar a captura de tela, porque não há espaço suficiente"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"O app ou a organização não permitem capturas de tela"</string> diff --git a/packages/SystemUI/res/values-pt/strings_tv.xml b/packages/SystemUI/res/values-pt/strings_tv.xml index 49b923d076b7..2ea81526feed 100644 --- a/packages/SystemUI/res/values-pt/strings_tv.xml +++ b/packages/SystemUI/res/values-pt/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN está conectada"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN está desconectada"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificações"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nenhuma notificação"</string> </resources> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 81caf56e4939..123d6721e5b8 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Captură de ecran salvată"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Atingeți pentru a vedea captura de ecran"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Nu s-a putut salva captura de ecran"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pentru a salva captura de ecran, trebuie să deblocați dispozitivul"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Încercați să faceți din nou o captură de ecran"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Captura de ecran nu poate fi salvată din cauza spațiului de stocare limitat"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Crearea capturilor de ecran nu este permisă de aplicație sau de organizația dvs."</string> diff --git a/packages/SystemUI/res/values-ro/strings_tv.xml b/packages/SystemUI/res/values-ro/strings_tv.xml index 69a31383a6cc..c64a492c59e4 100644 --- a/packages/SystemUI/res/values-ro/strings_tv.xml +++ b/packages/SystemUI/res/values-ro/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN este conectat"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN este deconectat"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Prin <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificări"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nicio notificare"</string> </resources> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index bf5e6047a525..03f1dfc831b0 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сохранен"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Нажмите, чтобы увидеть скриншот."</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Не удалось сохранить скриншот"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Чтобы сохранить скриншот, разблокируйте устройство."</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Попробуйте сделать скриншот снова."</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Не удалось сохранить скриншот: недостаточно места."</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Не удалось сделать скриншот: нет разрешения от приложения или организации."</string> diff --git a/packages/SystemUI/res/values-ru/strings_tv.xml b/packages/SystemUI/res/values-ru/strings_tv.xml index bd8855bb1b56..e08ade3bc065 100644 --- a/packages/SystemUI/res/values-ru/strings_tv.xml +++ b/packages/SystemUI/res/values-ru/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN-подключение установлено"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN-подключение отключено"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Отправлено через <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Уведомления"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Уведомлений нет."</string> </resources> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index c855be3dd624..f5e2e706e5d3 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"තිර රුව සුරකින ලදී"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"ඔබගේ තිර රුව බැලීමට තට්ටු කරන්න"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"තිර රුව සුරැකිය නොහැකි විය"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"තිර රුව සුරැකීමට පෙර උපාංගය අගුලු හැරිය යුතුය"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"තිර රුව නැවත ගැනීමට උත්සාහ කරන්න"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"සීමිත ගබඩා ඉඩ නිසා තිර රුව සුරැකිය නොහැකිය"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"තිර රූ ගැනීමට යෙදුම හෝ ඔබගේ සංවිධානය ඉඩ නොදේ"</string> diff --git a/packages/SystemUI/res/values-si/strings_tv.xml b/packages/SystemUI/res/values-si/strings_tv.xml index a04d166ebea3..3067be345c7d 100644 --- a/packages/SystemUI/res/values-si/strings_tv.xml +++ b/packages/SystemUI/res/values-si/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN සම්බන්ධිතයි"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN විසන්ධි කර ඇත"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> හරහා"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"දැනුම්දීම්"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"දැනුම්දීම් නැත"</string> </resources> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index c2a94be4ad2d..22673b94ee07 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Snímka obrazovky bola uložená"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Klepnutím zobrazíte snímku obrazovky"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Snímku obrazovky sa nepodarilo uložiť"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pred uložením snímky obrazovky je potrebné zariadenie odomknúť"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Skúste snímku urobiť znova"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Snímka obrazovky sa nedá uložiť z dôvodu nedostatku miesta v úložisku"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Vytváranie snímok obrazovky je zakázané aplikáciou alebo vašou organizáciou"</string> diff --git a/packages/SystemUI/res/values-sk/strings_tv.xml b/packages/SystemUI/res/values-sk/strings_tv.xml index 3b8fcc836c66..b37648da0e7d 100644 --- a/packages/SystemUI/res/values-sk/strings_tv.xml +++ b/packages/SystemUI/res/values-sk/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Sieť VPN je pripojená"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Sieť VPN je odpojená"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Cez: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Upozornenia"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Žiadne upozornenia"</string> </resources> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 5828d659efb4..42a961ceead7 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Posnetek zaslona je shranjen"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Dotaknite se, če si želite ogledati posnetek zaslona"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Posnetka zaslona ni bilo mogoče shraniti"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pred shranjevanjem posnetka zaslona morate odkleniti napravo"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Poskusite znova ustvariti posnetek zaslona"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Shranjevanje posnetka zaslona ni mogoče zaradi omejenega prostora za shranjevanje"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikacija ali vaša organizacija ne dovoljuje posnetkov zaslona"</string> diff --git a/packages/SystemUI/res/values-sl/strings_tv.xml b/packages/SystemUI/res/values-sl/strings_tv.xml index af5d75db1a56..57d70c0c3ecb 100644 --- a/packages/SystemUI/res/values-sl/strings_tv.xml +++ b/packages/SystemUI/res/values-sl/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Povezava z navideznim zasebnim omrežjem je vzpostavljena"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Povezava z navideznim zasebnim omrežjem je prekinjena"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Prek storitve <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Obvestila"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ni obvestil"</string> </resources> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index 297ebc6e6a3c..19438233c5a3 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Pamja e ekranit u ruajt"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Trokit për të parë pamjen e ekranit"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Pamja e ekranit nuk mund të ruhej"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pajisja duhet të shkyçet para se të mund të ruhet pamja e ekranit"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Provo ta nxjerrësh përsëri pamjen e ekranit"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Pamja e ekranit nuk mund të ruhet për shkak të hapësirës ruajtëse të kufizuar"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Nxjerrja e pamjeve të ekranit nuk lejohet nga aplikacioni ose organizata jote."</string> diff --git a/packages/SystemUI/res/values-sq/strings_tv.xml b/packages/SystemUI/res/values-sq/strings_tv.xml index 713130f30879..fb74e38b4f38 100644 --- a/packages/SystemUI/res/values-sq/strings_tv.xml +++ b/packages/SystemUI/res/values-sq/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN-ja është e lidhur"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN-ja është shkëputur"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Nëpërmjet <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Njoftimet"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Asnjë njoftim"</string> </resources> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index f9262b0e48be..50bbff217bac 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Снимак екрана је сачуван"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Додирните да бисте видели снимак екрана"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Чување снимка екрана није успело"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Уређај мора да буде откључан да би снимак екрана могао да се сачува"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Пробајте да поново направите снимак екрана"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Чување снимка екрана није успело због ограниченог меморијског простора"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Апликација или организација не дозвољавају прављење снимака екрана"</string> diff --git a/packages/SystemUI/res/values-sr/strings_tv.xml b/packages/SystemUI/res/values-sr/strings_tv.xml index 77f842c5d1fd..59151da2677f 100644 --- a/packages/SystemUI/res/values-sr/strings_tv.xml +++ b/packages/SystemUI/res/values-sr/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN је повезан"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Веза са VPN-ом је прекинута"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Преко: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Обавештења"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Нема обавештења"</string> </resources> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 3401294139da..1aba0e335d59 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Skärmdumpen har sparats"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Visa skärmdumpen genom att trycka här"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Det gick inte att spara skärmdumpen"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Skärmdumpen kan bara sparas om enheten är upplåst"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Testa att ta en skärmdump igen"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Det går inte att spara skärmdumpen eftersom lagringsutrymmet inte räcker"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Appen eller organisationen tillåter inte att du tar skärmdumpar"</string> diff --git a/packages/SystemUI/res/values-sv/strings_tv.xml b/packages/SystemUI/res/values-sv/strings_tv.xml index 141aabf207aa..d7261e6b1445 100644 --- a/packages/SystemUI/res/values-sv/strings_tv.xml +++ b/packages/SystemUI/res/values-sv/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN är anslutet"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN är frånkopplat"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Aviseringar"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Inga aviseringar"</string> </resources> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 4cf09c775c20..f02cc912d2de 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Imehifadhi picha ya skrini"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Gusa ili utazame picha ya skrini uliyohifadhi"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Imeshindwa kuhifadhi picha ya skrini"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Ni sharti ufungue kifaa kabla ya kuhifadhi picha ya skrini"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Jaribu kupiga picha ya skrini tena"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Imeshindwa kuhifadhi picha ya skrini kwa sababu nafasi haitoshi"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Programu au shirika lako halikuruhusu kupiga picha za skrini"</string> diff --git a/packages/SystemUI/res/values-sw/strings_tv.xml b/packages/SystemUI/res/values-sw/strings_tv.xml index 9dd37ce63bb3..8f6880d4bd0b 100644 --- a/packages/SystemUI/res/values-sw/strings_tv.xml +++ b/packages/SystemUI/res/values-sw/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN imeunganishwa"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN imeondolewa"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Kupitia <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Arifa"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Hakuna Arifa"</string> </resources> diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml index be66320975d9..d886f00cf028 100644 --- a/packages/SystemUI/res/values-sw600dp/config.xml +++ b/packages/SystemUI/res/values-sw600dp/config.xml @@ -32,4 +32,7 @@ <!-- orientation of the dead zone when touches have recently occurred elsewhere on screen --> <integer name="navigation_bar_deadzone_orientation">0</integer> + <!-- Whether wallet view is shown in landscape / seascape orientations --> + <bool name="global_actions_show_landscape_wallet_view">true</bool> + </resources> diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml index fdf4e3b1b796..3be73ba8df25 100644 --- a/packages/SystemUI/res/values-sw600dp/dimens.xml +++ b/packages/SystemUI/res/values-sw600dp/dimens.xml @@ -94,4 +94,11 @@ <!-- Text size for user name in user switcher --> <dimen name="kg_user_switcher_text_size">18sp</dimen> + + <!-- TODO(himanshujaju) - add comments --> + <dimen name="global_actions_wallet_top_margin">5dp</dimen> + <dimen name="controls_header_bottom_margin">12dp</dimen> + <dimen name="controls_top_margin">24dp</dimen> + + <dimen name="global_actions_grid_item_layout_height">80dp</dimen> </resources> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 5d29c91998bf..a9a3b07a1389 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"ஸ்கிரீன்ஷாட் சேமிக்கப்பட்டது"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"ஸ்கிரீன்ஷாட்டைப் பார்க்க, தட்டவும்"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"ஸ்கிரீன் ஷாட்டைச் சேமிக்க முடியவில்லை"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ஸ்கிரீன்ஷாட் சேமிக்கப்படுவதற்கு முன்பு சாதனம் அன்லாக் செய்யப்பட வேண்டும்"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ஸ்கிரீன் ஷாட்டை மீண்டும் எடுக்க முயலவும்"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"போதுமான சேமிப்பிடம் இல்லாததால் ஸ்கிரீன்ஷாட்டைச் சேமிக்க முடியவில்லை"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ஸ்கிரீன் ஷாட்டுகளை எடுப்பதை, ஆப்ஸ் அல்லது உங்கள் நிறுவனம் அனுமதிக்கவில்லை"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"பொதுச் செய்திகள்"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"சேமிப்பிடம்"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"குறிப்புகள்"</string> - <string name="instant_apps" msgid="8337185853050247304">"இன்ஸ்டண்ட் ஆப்ஸ்"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> இயங்குகிறது"</string> <string name="instant_apps_message" msgid="6112428971833011754">"நிறுவ வேண்டிய தேவையில்லாமல் ஆப்ஸ் திறக்கப்பட்டது."</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"நிறுவ வேண்டிய தேவையில்லாமல் ஆப்ஸ் திறக்கப்பட்டது. மேலும் அறியத் தட்டவும்."</string> diff --git a/packages/SystemUI/res/values-ta/strings_tv.xml b/packages/SystemUI/res/values-ta/strings_tv.xml index 04832016cf67..9c62d8cf7b96 100644 --- a/packages/SystemUI/res/values-ta/strings_tv.xml +++ b/packages/SystemUI/res/values-ta/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN இணைக்கப்பட்டது"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN துண்டிக்கப்பட்டது"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> வழியாக"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"அறிவிப்புகள்"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"அறிவிப்புகள் எதுவுமில்லை"</string> </resources> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 5fed052d9f5b..7e7dc374af20 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"స్క్రీన్షాట్ సేవ్ చేయబడింది"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"మీ స్క్రీన్షాట్ను వీక్షించడానికి నొక్కండి"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"స్క్రీన్షాట్ని సేవ్ చేయడం సాధ్యం కాలేదు"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"స్క్రీన్షాట్ సేవ్ అవ్వకముందే పరికరం అన్లాక్ చేయబడాలి"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"స్క్రీన్షాట్ తీయడానికి మళ్లీ ప్రయత్నించండి"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"నిల్వ స్థలం పరిమితంగా ఉన్న కారణంగా స్క్రీన్షాట్ను సేవ్ చేయడం సాధ్యపడదు"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"స్క్రీన్షాట్లు తీయడానికి యాప్ లేదా మీ సంస్థ అనుమతించలేదు"</string> diff --git a/packages/SystemUI/res/values-te/strings_tv.xml b/packages/SystemUI/res/values-te/strings_tv.xml index 67fb678466cb..50f4b4531eb7 100644 --- a/packages/SystemUI/res/values-te/strings_tv.xml +++ b/packages/SystemUI/res/values-te/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN కనెక్ట్ చేయబడింది"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN డిస్కనెక్ట్ చేయబడింది"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ద్వారా"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"నోటిఫికేషన్లు"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"నోటిఫికేషన్లు లేవు"</string> </resources> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index ffa84d3531ee..a18ec8acecf8 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"บันทึกภาพหน้าจอแล้ว"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"แตะเพื่อดูภาพหน้าจอ"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"บันทึกภาพหน้าจอไม่ได้"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ต้องปลดล็อกอุปกรณ์ก่อนจึงจะบันทึกภาพหน้าจอได้"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ลองบันทึกภาพหน้าจออีกครั้ง"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"บันทึกภาพหน้าจอไม่ได้เนื่องจากพื้นที่เก็บข้อมูลมีจำกัด"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"แอปหรือองค์กรของคุณไม่อนุญาตให้จับภาพหน้าจอ"</string> diff --git a/packages/SystemUI/res/values-th/strings_tv.xml b/packages/SystemUI/res/values-th/strings_tv.xml index 4a9144b227fa..072482176363 100644 --- a/packages/SystemUI/res/values-th/strings_tv.xml +++ b/packages/SystemUI/res/values-th/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"เชื่อมต่อ VPN แล้ว"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"ยกเลิกการเชื่อมต่อ VPN แล้ว"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ผ่าน <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"การแจ้งเตือน"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ไม่มีการแจ้งเตือน"</string> </resources> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index b8cdef1979ad..a68f5adfb446 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Na-save ang screenshot"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"I-tap upang tingnan ang iyong screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Hindi ma-save ang screenshot"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Dapat naka-unlock ang device bago ma-save ang screenshot"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Subukang kumuhang muli ng screenshot"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Hindi ma-save ang screenshot dahil sa limitadong espasyo ng storage"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Hindi pinahihintulutan ng app o ng iyong organisasyon ang pagkuha ng mga screenshot"</string> diff --git a/packages/SystemUI/res/values-tl/strings_tv.xml b/packages/SystemUI/res/values-tl/strings_tv.xml index 3489503652ea..8dcc22f2d36b 100644 --- a/packages/SystemUI/res/values-tl/strings_tv.xml +++ b/packages/SystemUI/res/values-tl/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Nakakonekta ang VPN"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Nakadiskonekta ang VPN"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Sa pamamagitan ng <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Mga Notification"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Walang Notification"</string> </resources> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 74666b2ec0c3..d0d343cea159 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekran görüntüsü kaydedildi"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Ekran görüntünüzü görmek için dokunun"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekran görüntüsü kaydedilemedi"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Ekran görüntüsünün kaydedilebilmesi için cihazın kilidi açık olmalıdır"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Tekrar ekran görüntüsü almayı deneyin"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Depolama alanı sınırlı olduğundan ekran görüntüsü kaydedilemiyor"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Uygulama veya kuruluşunuz, ekran görüntüsü alınmasına izin vermiyor."</string> diff --git a/packages/SystemUI/res/values-tr/strings_tv.xml b/packages/SystemUI/res/values-tr/strings_tv.xml index bfb1ae24c890..babd460a1375 100644 --- a/packages/SystemUI/res/values-tr/strings_tv.xml +++ b/packages/SystemUI/res/values-tr/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN bağlandı"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN bağlantısı kesildi"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> yoluyla"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Bildirimler"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Bildirim Yok"</string> </resources> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 2737ce892f71..26bc66277d4e 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -28,7 +28,7 @@ <string name="battery_low_percent_format" msgid="4276661262843170964">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> <string name="battery_low_percent_format_hybrid" msgid="3985614339605686167">"На основі використання залишилося <xliff:g id="PERCENTAGE">%1$s</xliff:g> – близько <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="battery_low_percent_format_hybrid_short" msgid="5917433188456218857">"Залишилося <xliff:g id="PERCENTAGE">%1$s</xliff:g> – близько <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g>. Увімкнено режим економії заряду акумулятора."</string> + <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g>. Увімкнено режим енергозбереження."</string> <string name="invalid_charger" msgid="4370074072117767416">"Не вдається зарядити через USB. Використовуйте зарядний пристрій, який входить у комплект пристрою."</string> <string name="invalid_charger_title" msgid="938685362320735167">"Не вдається зарядити через USB"</string> <string name="invalid_charger_text" msgid="2339310107232691577">"Використовуйте зарядний пристрій, який входить у комплект пристрою"</string> @@ -36,7 +36,7 @@ <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Увімкнути режим енергозбереження?"</string> <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Про режим енергозбереження"</string> <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Увімкнути"</string> - <string name="battery_saver_start_action" msgid="4553256017945469937">"Увімкнути режим економії заряду акумулятора"</string> + <string name="battery_saver_start_action" msgid="4553256017945469937">"Увімкнути режим енергозбереження"</string> <string name="status_bar_settings_settings_button" msgid="534331565185171556">"Налаштування"</string> <string name="status_bar_settings_wifi_button" msgid="7243072479837270946">"Wi-Fi"</string> <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Автообертання екрана"</string> @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Знімок екрана збережено"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Торкніться, щоб переглянути знімок екрана"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Не вдалося зберегти знімок екрана"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Щоб зберегти знімок екрана, розблокуйте пристрій"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Спробуйте зробити знімок екрана ще раз"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Не вдалося зберегти знімок екрана через обмежений обсяг пам’яті"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Додаток або адміністратор вашої організації не дозволяють робити знімки екрана"</string> @@ -509,7 +510,7 @@ <string name="user_remove_user_remove" msgid="8387386066949061256">"Видалити"</string> <string name="battery_saver_notification_title" msgid="8419266546034372562">"Режим енергозбереження ввімкнено"</string> <string name="battery_saver_notification_text" msgid="2617841636449016951">"Знижується продуктивність і обмежуються фонові дані"</string> - <string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Вимкнути режим економії заряду акумулятора"</string> + <string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Вимкнути режим енергозбереження"</string> <string name="media_projection_dialog_text" msgid="1755705274910034772">"Додаток <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> матиме доступ до всієї інформації, яка з\'являється на екрані або відтворюється на пристрої під час запису чи трансляції, зокрема до паролів, інформації про платежі, фотографій, повідомлень і аудіофайлів."</string> <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Сервіс, що надає цю функцію, матиме доступ до всієї інформації, яка з\'являється на екрані або відтворюється на пристрої під час запису чи трансляції, зокрема до паролів, інформації про платежі, фотографій, повідомлень і аудіофайлів."</string> <string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Почати запис або трансляцію?"</string> @@ -975,11 +976,11 @@ <string name="slice_permission_checkbox" msgid="4242888137592298523">"Дозволити додатку <xliff:g id="APP">%1$s</xliff:g> показувати фрагменти будь-якого додатка"</string> <string name="slice_permission_allow" msgid="6340449521277951123">"Дозволити"</string> <string name="slice_permission_deny" msgid="6870256451658176895">"Заборонити"</string> - <string name="auto_saver_title" msgid="6873691178754086596">"Торкніться, щоб увімкнути автоматичний режим економії заряду акумулятора"</string> + <string name="auto_saver_title" msgid="6873691178754086596">"Торкніться, щоб налаштувати режим енергозбереження"</string> <string name="auto_saver_text" msgid="3214960308353838764">"Вмикати, коли заряд акумулятора закінчується"</string> <string name="no_auto_saver_action" msgid="7467924389609773835">"Ні, дякую"</string> <string name="auto_saver_enabled_title" msgid="4294726198280286333">"Автоматичний перехід у режим енергозбереження ввімкнено"</string> - <string name="auto_saver_enabled_text" msgid="7889491183116752719">"Режим економії заряду акумулятора вмикається автоматично, коли рівень заряду нижчий за <xliff:g id="PERCENTAGE">%d</xliff:g>%%."</string> + <string name="auto_saver_enabled_text" msgid="7889491183116752719">"Режим енергозбереження вмикається автоматично, коли рівень заряду нижчий за <xliff:g id="PERCENTAGE">%d</xliff:g>%%."</string> <string name="open_saver_setting_action" msgid="2111461909782935190">"Налаштування"</string> <string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string> <string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string> diff --git a/packages/SystemUI/res/values-uk/strings_tv.xml b/packages/SystemUI/res/values-uk/strings_tv.xml index 4a4cac92e6c1..170b06805355 100644 --- a/packages/SystemUI/res/values-uk/strings_tv.xml +++ b/packages/SystemUI/res/values-uk/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Мережу VPN під\'єднано"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Мережу VPN від\'єднано"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Через <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Сповіщення"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Немає сповіщень"</string> </resources> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 7488323b00c0..53072498974c 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"اسکرین شاٹ محفوظ ہو گیا"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"اپنا اسکرین شاٹ دیکھنے کیلئے تھپتھپائیں"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"اسکرین شاٹ کو محفوظ نہیں کیا جا سکا"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"اسکرین شاٹ محفوظ کرنے سے پہلے آلے کو غیر مقفل کرنا ضروری ہے"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"دوبارہ اسکرین شاٹ لینے کی کوشش کریں"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"اسٹوریج کی محدود جگہ کی وجہ سے اسکرین شاٹ کو محفوظ نہیں کیا جا سکتا"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ایپ یا آپ کی تنظیم کی جانب سے اسکرین شاٹس لینے کی اجازت نہیں ہے"</string> diff --git a/packages/SystemUI/res/values-ur/strings_tv.xml b/packages/SystemUI/res/values-ur/strings_tv.xml index 20d3a587af48..fbaa3f628bf3 100644 --- a/packages/SystemUI/res/values-ur/strings_tv.xml +++ b/packages/SystemUI/res/values-ur/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN منسلک ہے"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN غیر منسلک ہے"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"بذریعہ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"اطلاعات"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"کوئی اطلاع نہیں ہے"</string> </resources> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 997197da19cb..b2ba26d6b92e 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Skrinshot saqlandi"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Skrinshotni ochish uchun bosing"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Skrinshot saqlanmadi"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Skrinshotni saqlashdan oldin qurilma qulflanmagan boʻlishi lozim"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Qayta skrinshot olib ko‘ring"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Xotirada joy kamligi uchun skrinshot saqlanmadi"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ilova yoki tashkilotingiz skrinshot olishni taqiqlagan"</string> @@ -778,7 +779,7 @@ </plurals> <string name="battery_panel_title" msgid="5931157246673665963">"Batareya sarfi"</string> <string name="battery_detail_charging_summary" msgid="8821202155297559706">"Quvvat tejash rejimidan quvvatlash vaqtida foydalanib bo‘lmaydi"</string> - <string name="battery_detail_switch_title" msgid="6940976502957380405">"Quvvat tejash rejimi"</string> + <string name="battery_detail_switch_title" msgid="6940976502957380405">"Quvvat tejash"</string> <string name="battery_detail_switch_summary" msgid="3668748557848025990">"Unumdorlik pasayadi va fonda internetdan foydalanish cheklanadi"</string> <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> tugmasi"</string> <string name="keyboard_key_home" msgid="3734400625170020657">"Bosh ekran"</string> diff --git a/packages/SystemUI/res/values-uz/strings_tv.xml b/packages/SystemUI/res/values-uz/strings_tv.xml index fc4ecd34873f..f4b4b0853e69 100644 --- a/packages/SystemUI/res/values-uz/strings_tv.xml +++ b/packages/SystemUI/res/values-uz/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ulandi"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN uzildi"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> orqali"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Bildirishnomalar"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Bildirishnomalar yoʻq"</string> </resources> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 1acdbb51c859..a5d490041516 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Đã lưu ảnh chụp màn hình"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Nhấn để xem ảnh chụp màn hình của bạn"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Không thể lưu ảnh chụp màn hình"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Bạn phải mở khóa thiết bị để chúng tôi có thể lưu ảnh chụp màn hình"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Hãy thử chụp lại màn hình"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Không thể lưu ảnh chụp màn hình do giới hạn dung lượng bộ nhớ"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ứng dụng hoặc tổ chức của bạn không cho phép chụp ảnh màn hình"</string> diff --git a/packages/SystemUI/res/values-vi/strings_tv.xml b/packages/SystemUI/res/values-vi/strings_tv.xml index 98697fd93204..3dfc8c186205 100644 --- a/packages/SystemUI/res/values-vi/strings_tv.xml +++ b/packages/SystemUI/res/values-vi/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN đã được kết nối"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN đã bị ngắt kết nối"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Thông qua <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Thông báo"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Không có thông báo"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 68630bba8212..10873c5ca125 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"已保存屏幕截图"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"点按即可查看您的屏幕截图"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"无法保存屏幕截图"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"必须先解锁设备,然后才能保存屏幕截图"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"请再次尝试截屏"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"由于存储空间有限,无法保存屏幕截图"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"此应用或您所在的单位不允许进行屏幕截图"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml index 169d98a538ed..1e599cabcd0b 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN 已连接"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN 已断开连接"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"通过“<xliff:g id="VPN_APP">%1$s</xliff:g>”"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"没有通知"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index ddf60fb56e20..9abcf109d9f9 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"螢幕擷取畫面已儲存"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"輕按即可查看螢幕擷取畫面"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"無法儲存螢幕擷取畫面"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"必須先解鎖裝置,才能儲存螢幕截圖"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"請再嘗試拍攝螢幕擷取畫面"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"由於儲存空間有限,因此無法儲存螢幕擷取畫面"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"應用程式或您的機構不允許擷取螢幕畫面"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml index 858185186365..92b176261f7b 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN 已連線"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN 已中斷連線"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"透過 <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"沒有通知"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 85aae2e9453b..a33146bd57e3 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"螢幕截圖已儲存"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"輕觸即可查看螢幕截圖"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"無法儲存螢幕截圖"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"必須先解鎖裝置,才能儲存螢幕截圖"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"請再次嘗試拍攝螢幕截圖"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"由於儲存空間有限,因此無法儲存螢幕截圖"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"這個應用程式或貴機構不允許擷取螢幕畫面"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml index fcb16b79c3ad..db0781acf3b5 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN 已連線"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN 連線已中斷"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"透過「<xliff:g id="VPN_APP">%1$s</xliff:g>」"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"沒有通知"</string> </resources> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index ca87d975e42e..5c8b6cd4d5df 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Isithombe-skrini silondoloziwe"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Thepha ukuze ubuke isithombe-skrini sakho"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Ayikwazanga ukulondoloza isithombe-skrini"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Idivayisi kufanele ivulwe ngaphambi kokuthi isithombe-skrini singalondolozwa"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Zama ukuthatha isithombe-skrini futhi"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Ayikwazi ukulondoloza isithombe-skrini ngenxa yesikhala sesitoreji esikhawulelwe"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ukuthatha izithombe-skrini akuvunyelwe uhlelo lokusebenza noma inhlangano yakho"</string> diff --git a/packages/SystemUI/res/values-zu/strings_tv.xml b/packages/SystemUI/res/values-zu/strings_tv.xml index 5cb6c1d1796e..a9b759766078 100644 --- a/packages/SystemUI/res/values-zu/strings_tv.xml +++ b/packages/SystemUI/res/values-zu/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"I-VPN ixhunyiwe"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"I-VPN inqanyuliwe"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Nge-<xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Izaziso"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Azikho Izaziso"</string> </resources> diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml index 78d92c4b47e2..897e3902b55c 100644 --- a/packages/SystemUI/res/values/attrs.xml +++ b/packages/SystemUI/res/values/attrs.xml @@ -161,5 +161,11 @@ <attr name="sensorPressureCoefficient" format="float"/> <attr name="sensorTouchAreaCoefficient" format="float"/> </declare-styleable> + + <declare-styleable name="AlphaTintDrawableWrapper"> + <attr name="android:tint" /> + <attr name="android:drawable" /> + <attr name="android:alpha" /> + </declare-styleable> </resources> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index c51e0bf2c31b..9731d786eb7f 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -35,8 +35,7 @@ <color name="status_bar_clock_color">#FFFFFFFF</color> <color name="qs_user_detail_icon_muted">#FFFFFFFF</color> <!-- not so muted after all --> <color name="qs_tile_disabled_color">#9E9E9E</color> <!-- 38% black --> - <color name="qs_customize_background">@color/GM2_grey_50</color> - <color name="qs_customize_decoration">@color/GM2_grey_100</color> + <color name="qs_customize_decoration">@color/GM2_grey_300</color> <!-- The color of the background in the separated list of the Global Actions menu --> <color name="global_actions_separated_background">#F5F5F5</color> @@ -257,6 +256,8 @@ <color name="control_enabled_heat_foreground">#FF8B66</color> <color name="control_enabled_default_foreground">@color/GM2_blue_300</color> <color name="control_enabled_cool_foreground">@color/GM2_blue_300</color> + <color name="control_thumbnail_tint">#33000000</color> + <color name="control_thumbnail_shadow_color">@*android:color/black</color> <!-- Docked misalignment message --> <color name="misalignment_text_color">#F28B82</color> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 880dd378e390..2bf513c604bd 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -570,4 +570,7 @@ <bool name="config_showNotificationForUnknownBatteryState">false</bool> <!-- content URL in a notification when ACTION_BATTERY_CHANGED.EXTRA_PRESENT field is false --> <string translatable="false" name="config_batteryStateUnknownUrl"></string> + + <!-- Whether wallet view is shown in landscape / seascape orientations --> + <bool name="global_actions_show_landscape_wallet_view">false</bool> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 57e1d43bc6ef..e1f7e7e56726 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1005,6 +1005,7 @@ <dimen name="global_actions_grid_vertical_padding">3dp</dimen> <dimen name="global_actions_grid_horizontal_padding">3dp</dimen> + <dimen name="global_actions_grid_item_layout_height">98dp</dimen> <dimen name="global_actions_grid_item_side_margin">5dp</dimen> <dimen name="global_actions_grid_item_vertical_margin">4dp</dimen> <dimen name="global_actions_grid_item_width">64dp</dimen> @@ -1194,8 +1195,8 @@ <dimen name="magnification_frame_move_long">25dp</dimen> <dimen name="magnification_drag_view_size">38dp</dimen> <dimen name="magnification_controls_size">90dp</dimen> - <dimen name="magnification_switch_button_size">32dp</dimen> - <dimen name="magnification_switch_button_padding">8dp</dimen> + <dimen name="magnification_switch_button_size">60dp</dimen> + <dimen name="magnification_switch_button_padding">12dp</dimen> <dimen name="magnifier_left_right_controls_width">35dp</dimen> <dimen name="magnifier_left_right_controls_height">45dp</dimen> <dimen name="magnifier_up_down_controls_width">45dp</dimen> @@ -1269,6 +1270,10 @@ <dimen name="controls_app_divider_height">2dp</dimen> <dimen name="controls_app_divider_side_margin">32dp</dimen> + <item name="controls_thumbnail_shadow_x" type="dimen" format="float">2.0</item> + <item name="controls_thumbnail_shadow_y" type="dimen" format="float">2.0</item> + <item name="controls_thumbnail_shadow_radius" type="dimen" format="float">2.0</item> + <dimen name="controls_card_margin">@dimen/control_base_item_margin</dimen> <item name="control_card_elevation" type="dimen" format="float">15</item> @@ -1303,6 +1308,7 @@ <dimen name="media_output_dialog_icon_corner_radius">16dp</dimen> <dimen name="media_output_dialog_title_anim_y_delta">12.5dp</dimen> - <dimen name="people_space_widget_radius">10dp</dimen> + <dimen name="people_space_widget_radius">24dp</dimen> + <dimen name="people_space_widget_round_radius">100dp</dimen> <dimen name="people_space_widget_background_padding">6dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 5b74687c3109..7989b7a08fc8 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2824,13 +2824,15 @@ <string name="build_number_copy_toast">Build number copied to clipboard.</string> <!-- Status for last interaction with exact time [CHAR LIMIT=120] --> - <string name="last_interaction_status" translatable="false">You last chatted <xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string> + <string name="last_interaction_status" translatable="false">Last chatted <xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string> <!-- Status for last interaction when less than a certain time window [CHAR LIMIT=120] --> - <string name="last_interaction_status_less_than" translatable="false">You last chatted less than <xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string> + <string name="last_interaction_status_less_than" translatable="false">Last chatted less than <xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string> <!-- Status for last interaction when over a certain time window [CHAR LIMIT=120] --> - <string name="last_interaction_status_over" translatable="false">You last chatted over <xliff:g id="duration" example="1 week">%1$s</xliff:g> ago</string> + <string name="last_interaction_status_over" translatable="false">Last chatted over <xliff:g id="duration" example="1 week">%1$s</xliff:g> ago</string> <!-- Status for conversation without interaction data [CHAR LIMIT=120] --> <string name="basic_status" translatable="false">Open conversation</string> + <!-- Status for conversation without interaction data [CHAR LIMIT=120] --> + <string name="select_conversation_text" translatable="false">Select one conversation to show in your widget:</string> <!-- Title to display in a notification when ACTION_BATTERY_CHANGED.EXTRA_PRESENT field is false [CHAR LIMIT=NONE] --> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 0697c5c0084c..6c0635a3ce51 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -489,7 +489,6 @@ <style name="TextAppearance.NotificationInfo"> <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item> - <item name="android:textColor">@color/notification_primary_text_color</item> </style> <style name="TextAppearance.NotificationInfo.Secondary"> @@ -498,7 +497,6 @@ </style> <style name="TextAppearance.NotificationInfo.Title"> - <item name="android:textColor">@color/notification_primary_text_color</item> <item name="android:textStyle">bold</item> </style> diff --git a/packages/SystemUI/res/xml/people_space_widget_info.xml b/packages/SystemUI/res/xml/people_space_widget_info.xml index f08c8c80f961..10e28c45a3b7 100644 --- a/packages/SystemUI/res/xml/people_space_widget_info.xml +++ b/packages/SystemUI/res/xml/people_space_widget_info.xml @@ -15,10 +15,11 @@ --> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" - android:minWidth="72dp" - android:minHeight="150dp" + android:minWidth="180dp" + android:minHeight="40dp" android:updatePeriodMillis="60000" - android:previewImage="@drawable/cloud" + android:previewImage="@drawable/ic_android" android:resizeMode="horizontal|vertical" + android:configure="com.android.systemui.people.PeopleSpaceActivity" android:initialLayout="@layout/people_space_widget"> </appwidget-provider> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java index c8607df8fe0b..ee7030a8cf5f 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java @@ -386,7 +386,10 @@ public class PluginInstanceManager<T extends Plugin> { } Intent i = new Intent(PluginManagerImpl.DISABLE_PLUGIN).setData( Uri.parse("package://" + component.flattenToString())); - PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, 0); + // TODO(b/174161910) Please replace FLAG_MUTABLE_UNAUDITED below + // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. + PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, + PendingIntent.FLAG_MUTABLE_UNAUDITED); nb.addAction(new Action.Builder(null, "Disable plugin", pi).build()); mContext.getSystemService(NotificationManager.class) .notify(SystemMessage.NOTE_PLUGIN, nb.build()); diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/BitmapUtil.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/BitmapUtil.java index b79fcbd43972..325bcfc622d7 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/BitmapUtil.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/BitmapUtil.java @@ -81,6 +81,7 @@ public final class BitmapUtil { HardwareBuffer buffer = bundle.getParcelable(KEY_BUFFER); ParcelableColorSpace colorSpace = bundle.getParcelable(KEY_COLOR_SPACE); - return Bitmap.wrapHardwareBuffer(Objects.requireNonNull(buffer), colorSpace); + return Bitmap.wrapHardwareBuffer(Objects.requireNonNull(buffer), + colorSpace.getColorSpace()); } } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java index e40185c279a8..267debc7dc2d 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java @@ -23,6 +23,7 @@ import android.content.Context; import android.content.pm.ActivityInfo; import android.graphics.PixelFormat; import android.graphics.PointF; +import android.graphics.Rect; import android.os.Bundle; import android.os.UserHandle; import android.provider.Settings; @@ -41,6 +42,8 @@ import android.widget.ImageView; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.R; +import java.util.Collections; + /** * Shows/hides a {@link android.widget.ImageView} on the screen and changes the values of * {@link Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE} when the UI is toggled. @@ -52,7 +55,7 @@ class MagnificationModeSwitch { @VisibleForTesting static final long FADING_ANIMATION_DURATION_MS = 300; @VisibleForTesting - static final int DEFAULT_FADE_OUT_ANIMATION_DELAY_MS = 3000; + static final int DEFAULT_FADE_OUT_ANIMATION_DELAY_MS = 5000; private int mUiTimeout; private final Runnable mFadeInAnimationTask; private final Runnable mFadeOutAnimationTask; @@ -85,7 +88,6 @@ class MagnificationModeSwitch { mImageView = imageView; mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop(); applyResourcesValues(); - mImageView.setImageResource(getIconResId(mMagnificationMode)); mImageView.setOnTouchListener(this::onTouch); mImageView.setAccessibilityDelegate(new View.AccessibilityDelegate() { @Override @@ -138,6 +140,7 @@ class MagnificationModeSwitch { final int padding = mContext.getResources().getDimensionPixelSize( R.dimen.magnification_switch_button_padding); mImageView.setPadding(padding, padding, padding, padding); + mImageView.setImageResource(getIconResId(mMagnificationMode)); } private boolean onTouch(View v, MotionEvent event) { @@ -205,6 +208,8 @@ class MagnificationModeSwitch { } if (!mIsVisible) { mWindowManager.addView(mImageView, mParams); + // Exclude magnification switch button from system gesture area. + setSystemGestureExclusion(); mIsVisible = true; mImageView.postOnAnimation(mFadeInAnimationTask); mUiTimeout = mAccessibilityManager.getRecommendedTimeoutMillis( @@ -224,7 +229,11 @@ class MagnificationModeSwitch { void onConfigurationChanged(int configDiff) { if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0) { applyResourcesValues(); - mImageView.setImageResource(getIconResId(mMagnificationMode)); + if (mIsVisible) { + mWindowManager.updateViewLayout(mImageView, mParams); + // Exclude magnification switch button from system gesture area. + setSystemGestureExclusion(); + } return; } if ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0) { @@ -261,7 +270,6 @@ class MagnificationModeSwitch { ImageView imageView = new ImageView(context); imageView.setClickable(true); imageView.setFocusable(true); - imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); imageView.setAlpha(0f); return imageView; } @@ -288,4 +296,13 @@ class MagnificationModeSwitch { private static String getAccessibilityWindowTitle(Context context) { return context.getString(com.android.internal.R.string.android_system_label); } + + private void setSystemGestureExclusion() { + mImageView.post(() -> { + mImageView.setSystemGestureExclusionRects( + Collections.singletonList( + new Rect(0, 0, mImageView.getWidth(), mImageView.getHeight()))); + }); + } + } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java index e49a5be58cfc..e6ad1cb9ea88 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java @@ -400,7 +400,10 @@ public class SystemActions extends SystemUI { case INTENT_ACTION_ACCESSIBILITY_SHORTCUT: { Intent intent = new Intent(intentAction); intent.setPackage(context.getPackageName()); - return PendingIntent.getBroadcast(context, 0, intent, 0); + // TODO(b/173157883) Please replace FLAG_MUTABLE_UNAUDITED below + // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. + return PendingIntent.getBroadcast(context, 0, intent, + PendingIntent.FLAG_MUTABLE_UNAUDITED); } default: break; diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java index e24a513437ea..e78057f5bd71 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java @@ -23,7 +23,6 @@ import android.net.Uri; import android.os.Build; import android.util.IndentingPrintWriter; import android.util.Log; -import android.view.MotionEvent; import androidx.annotation.NonNull; @@ -33,10 +32,12 @@ import com.android.systemui.dagger.qualifiers.TestHarness; import com.android.systemui.dock.DockManager; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.util.sensors.ThresholdSensor; +import com.android.systemui.util.time.SystemClock; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Locale; @@ -63,6 +64,8 @@ public class BrightLineFalsingManager implements FalsingManager { private final DockManager mDockManager; private final SingleTapClassifier mSingleTapClassifier; private final DoubleTapClassifier mDoubleTapClassifier; + private final HistoryTracker mHistoryTracker; + private final SystemClock mSystemClock; private final boolean mTestHarness; private final MetricsLogger mMetricsLogger; private int mIsFalseTouchCalls; @@ -85,6 +88,17 @@ public class BrightLineFalsingManager implements FalsingManager { } }; + private final FalsingDataProvider.GestureCompleteListener mGestureCompleteListener = + new FalsingDataProvider.GestureCompleteListener() { + @Override + public void onGestureComplete() { + mHistoryTracker.addResults( + mClassifiers.stream().map(FalsingClassifier::classifyGesture) + .collect(Collectors.toCollection(ArrayList::new)), + mSystemClock.uptimeMillis()); + } + }; + private boolean mPreviousResult = false; @Inject @@ -92,6 +106,7 @@ public class BrightLineFalsingManager implements FalsingManager { DockManager dockManager, MetricsLogger metricsLogger, @Named(BRIGHT_LINE_GESTURE_CLASSIFERS) Set<FalsingClassifier> classifiers, SingleTapClassifier singleTapClassifier, DoubleTapClassifier doubleTapClassifier, + HistoryTracker historyTracker, SystemClock systemClock, @TestHarness boolean testHarness) { mDataProvider = falsingDataProvider; mDockManager = dockManager; @@ -99,9 +114,12 @@ public class BrightLineFalsingManager implements FalsingManager { mClassifiers = classifiers; mSingleTapClassifier = singleTapClassifier; mDoubleTapClassifier = doubleTapClassifier; + mHistoryTracker = historyTracker; + mSystemClock = systemClock; mTestHarness = testHarness; mDataProvider.addSessionListener(mSessionListener); + mDataProvider.addGestureCompleteListener(mGestureCompleteListener); } @Override @@ -119,21 +137,22 @@ public class BrightLineFalsingManager implements FalsingManager { mPreviousResult = !mTestHarness && !mDataProvider.isJustUnlockedWithFace() && !mDockManager.isDocked() && mClassifiers.stream().anyMatch(falsingClassifier -> { - boolean result = falsingClassifier.isFalseTouch(); - if (result) { + FalsingClassifier.Result result = falsingClassifier.classifyGesture( + mHistoryTracker.falsePenalty(), mHistoryTracker.falseConfidence()); + if (result.isFalse()) { logInfo(String.format( (Locale) null, "{classifier=%s, interactionType=%d}", falsingClassifier.getClass().getName(), mDataProvider.getInteractionType())); - String reason = falsingClassifier.getReason(); + String reason = result.getReason(); if (reason != null) { logInfo(reason); } } else { logDebug(falsingClassifier.getClass().getName() + ": false"); } - return result; + return result.isFalse(); }); logDebug("Is false touch? " + mPreviousResult); @@ -159,10 +178,12 @@ public class BrightLineFalsingManager implements FalsingManager { @Override public boolean isFalseTap(boolean robustCheck) { - if (!mSingleTapClassifier.isTap(mDataProvider.getRecentMotionEvents())) { + FalsingClassifier.Result singleTapResult = + mSingleTapClassifier.isTap(mDataProvider.getRecentMotionEvents()); + if (singleTapResult.isFalse()) { logInfo(String.format( (Locale) null, "{classifier=%s}", mSingleTapClassifier.getClass().getName())); - String reason = mSingleTapClassifier.getReason(); + String reason = singleTapResult.getReason(); if (reason != null) { logInfo(reason); } @@ -179,23 +200,16 @@ public class BrightLineFalsingManager implements FalsingManager { @Override public boolean isFalseDoubleTap() { - boolean result = mDoubleTapClassifier.isFalseTouch(); - if (result) { + FalsingClassifier.Result result = mDoubleTapClassifier.classifyGesture(); + if (result.isFalse()) { logInfo(String.format( (Locale) null, "{classifier=%s}", mDoubleTapClassifier.getClass().getName())); - String reason = mDoubleTapClassifier.getReason(); + String reason = result.getReason(); if (reason != null) { logInfo(reason); } } - return result; - } - - @Override - public void onTouchEvent(MotionEvent motionEvent, int width, int height) { - // TODO: some of these classifiers might allow us to abort early, meaning we don't have to - // make these calls. - mClassifiers.forEach((classifier) -> classifier.onTouchEvent(motionEvent)); + return result.isFalse(); } @Override @@ -271,6 +285,8 @@ public class BrightLineFalsingManager implements FalsingManager { @Override public void cleanup() { mDataProvider.removeSessionListener(mSessionListener); + mDataProvider.removeGestureCompleteListener(mGestureCompleteListener); + mClassifiers.forEach(FalsingClassifier::cleanup); } static void logDebug(String msg) { diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java index 92dd8b74e959..bbb937176f59 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java @@ -62,17 +62,16 @@ class DiagonalClassifier extends FalsingClassifier { VERTICAL_ANGLE_RANGE); } - @Override - boolean isFalseTouch() { + Result calculateFalsingResult(double historyPenalty, double historyConfidence) { float angle = getAngle(); if (angle == Float.MAX_VALUE) { // Unknown angle - return false; + return Result.passed(0); } if (getInteractionType() == LEFT_AFFORDANCE || getInteractionType() == RIGHT_AFFORDANCE) { - return false; + return Result.passed(0); } float minAngle = DIAGONAL - mHorizontalAngleRange; @@ -82,15 +81,15 @@ class DiagonalClassifier extends FalsingClassifier { maxAngle = DIAGONAL + mVerticalAngleRange; } - return angleBetween(angle, minAngle, maxAngle) + boolean falsed = angleBetween(angle, minAngle, maxAngle) || angleBetween(angle, minAngle + NINETY_DEG, maxAngle + NINETY_DEG) || angleBetween(angle, minAngle - NINETY_DEG, maxAngle - NINETY_DEG) || angleBetween(angle, minAngle + ONE_HUNDRED_EIGHTY_DEG, maxAngle + ONE_HUNDRED_EIGHTY_DEG); + return falsed ? Result.falsed(0.5f, getReason()) : Result.passed(0.5); } - @Override - String getReason() { + private String getReason() { return String.format( (Locale) null, "{angle=%f, vertical=%s}", diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java index 50d55f6f6028..4cb5aa2cce37 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java @@ -123,7 +123,6 @@ class DistanceClassifier extends FalsingClassifier { } VelocityTracker velocityTracker = VelocityTracker.obtain(); - for (MotionEvent motionEvent : motionEvents) { velocityTracker.addMovement(motionEvent); } @@ -148,11 +147,11 @@ class DistanceClassifier extends FalsingClassifier { } @Override - public boolean isFalseTouch() { - return !getPassedFlingThreshold(); + Result calculateFalsingResult(double historyPenalty, double historyConfidence) { + return !getPassedFlingThreshold() + ? Result.falsed(0.5, getReason()) : Result.passed(0.5); } - @Override String getReason() { DistanceVectors distanceVectors = getDistances(); @@ -170,10 +169,10 @@ class DistanceClassifier extends FalsingClassifier { mVerticalSwipeThresholdPx); } - boolean isLongSwipe() { + Result isLongSwipe() { boolean longSwipe = getPassedDistanceThreshold(); logDebug("Is longSwipe? " + longSwipe); - return longSwipe; + return longSwipe ? Result.passed(0.5) : Result.falsed(0.5, getReason()); } private boolean getPassedDistanceThreshold() { diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java index 1c8f4208edba..64576a97ddb2 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java @@ -36,8 +36,6 @@ public class DoubleTapClassifier extends FalsingClassifier { private final float mDoubleTapSlop; private final long mDoubleTapTimeMs; - private StringBuilder mReason = new StringBuilder(); - @Inject DoubleTapClassifier(FalsingDataProvider dataProvider, SingleTapClassifier singleTapClassifier, @Named(DOUBLE_TAP_TOUCH_SLOP) float doubleTapSlop, @@ -49,32 +47,34 @@ public class DoubleTapClassifier extends FalsingClassifier { } @Override - boolean isFalseTouch() { + Result calculateFalsingResult(double historyPenalty, double historyConfidence) { List<MotionEvent> secondTapEvents = getRecentMotionEvents(); Queue<? extends List<MotionEvent>> historicalEvents = getHistoricalEvents(); List<MotionEvent> firstTapEvents = historicalEvents.peek(); - mReason = new StringBuilder(); + StringBuilder reason = new StringBuilder(); if (firstTapEvents == null) { - mReason.append("Only one gesture recorded"); - return true; + return Result.falsed(1, "Only one gesture recorded"); } - return !isDoubleTap(firstTapEvents, secondTapEvents, mReason); + return !isDoubleTap(firstTapEvents, secondTapEvents, reason) + ? Result.falsed(0.5, reason.toString()) : Result.passed(0.5); } /** Returns true if the two supplied lists of {@link MotionEvent}s look like a double-tap. */ public boolean isDoubleTap(List<MotionEvent> firstEvents, List<MotionEvent> secondEvents, StringBuilder reason) { - if (!mSingleTapClassifier.isTap(firstEvents)) { - reason.append("First gesture is not a tap. ").append(mSingleTapClassifier.getReason()); + Result firstTap = mSingleTapClassifier.isTap(firstEvents); + if (firstTap.isFalse()) { + reason.append("First gesture is not a tap. ").append(firstTap.getReason()); return false; } - if (!mSingleTapClassifier.isTap(secondEvents)) { - reason.append("Second gesture is not a tap. ").append(mSingleTapClassifier.getReason()); + Result secondTap = mSingleTapClassifier.isTap(secondEvents); + if (secondTap.isFalse()) { + reason.append("Second gesture is not a tap. ").append(secondTap.getReason()); return false; } @@ -106,9 +106,4 @@ public class DoubleTapClassifier extends FalsingClassifier { return true; } - - @Override - String getReason() { - return mReason.toString(); - } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java index 82575c3e639e..dbfeacfa91c4 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java @@ -29,8 +29,11 @@ import java.util.Queue; public abstract class FalsingClassifier { private final FalsingDataProvider mDataProvider; + private final FalsingDataProvider.MotionEventListener mMotionEventListener = this::onTouchEvent; + FalsingClassifier(FalsingDataProvider dataProvider) { mDataProvider = dataProvider; + mDataProvider.addMotionEventListener(mMotionEventListener); } List<MotionEvent> getRecentMotionEvents() { @@ -89,6 +92,10 @@ public abstract class FalsingClassifier { return mDataProvider.getInteractionType(); } + void cleanup() { + mDataProvider.removeMotionEventListener(mMotionEventListener); + } + /** * Called whenever a MotionEvent occurs. * @@ -113,17 +120,32 @@ public abstract class FalsingClassifier { void onSessionEnded() {}; /** - * Returns true if the data captured so far looks like a false touch. + * Returns whether a gesture looks like a false touch. + * + * See also {@link #classifyGesture(double, double)}. */ - abstract boolean isFalseTouch(); + Result classifyGesture() { + return calculateFalsingResult(0, 0); + } /** - * Give the classifier a chance to log more details about why it triggered. + * Returns whether a gesture looks like a false touch, with the option to consider history. + * + * Unlike the parameter-less version of this method, this method allows the classifier to take + * history into account, penalizing or boosting confidence in a gesture based on recent results. * - * This should only be called after a call to {@link #isFalseTouch()}, and only if - * {@link #isFalseTouch()} returns true; + * See also {@link #classifyGesture()}. */ - abstract String getReason(); + Result classifyGesture(double historyPenalty, double historyConfidence) { + return calculateFalsingResult(historyPenalty, historyConfidence); + } + + /** + * Calculate a result based on available data. + * + * When passed a historyConfidence of 0, the history penalty should be wholly ignored. + */ + abstract Result calculateFalsingResult(double historyPenalty, double historyConfidence); /** */ public static void logDebug(String msg) { @@ -139,4 +161,48 @@ public abstract class FalsingClassifier { public static void logError(String msg) { BrightLineFalsingManager.logError(msg); } + + /** + * A Falsing result that encapsulates the boolean result along with confidence and a reason. + */ + static class Result { + private final boolean mFalsed; + private final double mConfidence; + private final String mReason; + + /** + * See {@link #falsed(double, String)} abd {@link #passed(double)}. + */ + private Result(boolean falsed, double confidence, String reason) { + mFalsed = falsed; + mConfidence = confidence; + mReason = reason; + } + + public boolean isFalse() { + return mFalsed; + } + + public double getConfidence() { + return mConfidence; + } + + public String getReason() { + return mReason; + } + + /** + * Construct a "falsed" result indicating that a gesture should be treated as accidental. + */ + static Result falsed(double confidence, String reason) { + return new Result(true, confidence, reason); + } + + /** + * Construct a "passed" result indicating that a gesture should be allowed. + */ + static Result passed(double confidence) { + return new Result(false, confidence, null); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java index c05ce93f0c13..fe47162a1d4e 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java @@ -113,7 +113,7 @@ public interface FalsingCollector { void onBouncerHidden(); /** */ - void onTouchEvent(MotionEvent ev, int width, int height); + void onTouchEvent(MotionEvent ev); /** */ void cleanup(); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java index a5691118261a..fd059898f7a6 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java @@ -143,7 +143,7 @@ public class FalsingCollectorFake implements FalsingCollector { } @Override - public void onTouchEvent(MotionEvent ev, int width, int height) { + public void onTouchEvent(MotionEvent ev) { } @Override diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java index 3547392512a7..4c11ecf66956 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java @@ -244,9 +244,8 @@ class FalsingCollectorImpl implements FalsingCollector { } @Override - public void onTouchEvent(MotionEvent ev, int width, int height) { + public void onTouchEvent(MotionEvent ev) { mFalsingDataProvider.onMotionEvent(ev); - mFalsingManager.onTouchEvent(ev, width, height); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java index 009b311f2363..deb9e6dc442c 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java @@ -50,6 +50,8 @@ public class FalsingDataProvider { private final float mXdpi; private final float mYdpi; private final List<SessionListener> mSessionListeners = new ArrayList<>(); + private final List<MotionEventListener> mMotionEventListeners = new ArrayList<>(); + private final List<GestureCompleteListener> mGestuerCompleteListeners = new ArrayList<>(); private @Classifier.InteractionType int mInteractionType; private final Deque<TimeLimitedMotionEventBuffer> mExtendedMotionEvents = new LinkedList<>(); @@ -97,6 +99,8 @@ public class FalsingDataProvider { FalsingClassifier.logDebug("Size: " + mRecentMotionEvents.size()); + mMotionEventListeners.forEach(listener -> listener.onMotionEvent(motionEvent)); + mDirty = true; } @@ -321,6 +325,26 @@ public class FalsingDataProvider { mSessionListeners.remove(listener); } + /** Register a {@link MotionEventListener}. */ + public void addMotionEventListener(MotionEventListener listener) { + mMotionEventListeners.add(listener); + } + + /** Unegister a {@link MotionEventListener}. */ + public void removeMotionEventListener(MotionEventListener listener) { + mMotionEventListeners.remove(listener); + } + + /** Register a {@link GestureCompleteListener}. */ + public void addGestureCompleteListener(GestureCompleteListener listener) { + mGestuerCompleteListeners.add(listener); + } + + /** Unregister a {@link GestureCompleteListener}. */ + public void removeGestureCompleteListener(GestureCompleteListener listener) { + mGestuerCompleteListeners.remove(listener); + } + void onSessionStarted() { mSessionListeners.forEach(SessionListener::onSessionStarted); } @@ -353,4 +377,16 @@ public class FalsingDataProvider { /** Called when the lock screen exits and falsing-tracking ends. */ void onSessionEnded(); } + + /** Callback for receiving {@link android.view.MotionEvent}s as they are reported. */ + public interface MotionEventListener { + /** */ + void onMotionEvent(MotionEvent ev); + } + + /** Callback to be alerted when the current gesture ends. */ + public interface GestureCompleteListener { + /** */ + void onGestureComplete(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java index 32d27bcc01a6..d4d8d06b081b 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java @@ -17,7 +17,6 @@ package com.android.systemui.classifier; import android.net.Uri; -import android.view.MotionEvent; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.plugins.FalsingManager; @@ -117,11 +116,6 @@ public class FalsingManagerFake implements FalsingManager { } @Override - public void onTouchEvent(MotionEvent ev, int width, int height) { - - } - - @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java index d4f58c324d39..cbec0576e449 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java @@ -19,7 +19,6 @@ package com.android.systemui.classifier; import android.content.Context; import android.net.Uri; import android.provider.DeviceConfig; -import android.view.MotionEvent; import androidx.annotation.NonNull; @@ -162,11 +161,6 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable { } @Override - public void onTouchEvent(MotionEvent ev, int width, int height) { - mInternalFalsingManager.onTouchEvent(ev, width, height); - } - - @Override public void onProximityEvent(ThresholdSensor.ThresholdSensorEvent proximityEvent) { mInternalFalsingManager.onProximityEvent(proximityEvent); } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java b/packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java new file mode 100644 index 000000000000..8bd94a122707 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.classifier; + +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.util.time.SystemClock; + +import java.util.Collection; +import java.util.concurrent.DelayQueue; +import java.util.concurrent.Delayed; +import java.util.concurrent.TimeUnit; + +import javax.inject.Inject; + +/** + * A stateful class for tracking recent {@link FalsingManager} results. + * + * Can return a "penalty" based on recent gestures that may make it harder or easier to + * unlock a phone, as well as a "confidence" relating to how consistent recent falsing results + * have been. + */ +@SysUISingleton +public class HistoryTracker { + private static final double HISTORY_DECAY = 0.8f; + private static final long DECAY_INTERVAL_MS = 100; + // We expire items once their decay factor is below 0.001. + private static final double MINIMUM_SCORE = 0.001; + private static final long TOTAL_DECAY_TIME_MS = + DECAY_INTERVAL_MS * (long) (Math.log(MINIMUM_SCORE) / Math.log(HISTORY_DECAY)); + private final SystemClock mSystemClock; + + DelayQueue<CombinedResult> mResults = new DelayQueue<>(); + + @Inject + HistoryTracker(SystemClock systemClock) { + mSystemClock = systemClock; + } + + /** + * Returns how much the HistoryClassifier thinks the past events indicate pocket dialing. + * + * A result of 0 means that all prior gestures succeeded or there is no data to + * calculate a score with. Use {@link #falseConfidence()} to differentiate between the + * two cases. + * + * A result of 1 means that all prior gestures were very obviously false. The current gesture + * might be valid, but it should have a high-bar to be classified as such. + * + * See also {@link #falseConfidence()}. + */ + double falsePenalty() { + //noinspection StatementWithEmptyBody + while (mResults.poll() != null) { + // Empty out the expired results. + } + + if (mResults.isEmpty()) { + return 0; + } + + long nowMs = mSystemClock.uptimeMillis(); + return mResults.stream() + .map(result -> result.getDecayedScore(nowMs)) + .reduce(0.0, Double::sum) / mResults.size(); + } + + /** + * Returns how confident the HistoryClassifier is in its own score. + * + * A result of 0.0 means that there are no data to make a calculation with. The HistoryTracker's + * results have nothing to add and should not be considered. + * + * A result of 0.5 means that the data are not consistent with each other, sometimes falsing + * sometimes not. + * + * A result of 1 means that there are ample, fresh data to act upon that is all consistent + * with each other. + * + * See als {@link #falsePenalty()}. + */ + double falseConfidence() { + //noinspection StatementWithEmptyBody + while (mResults.poll() != null) { + // Empty out the expired results. + } + + // Our confidence is 1 - the population stddev. Smaller stddev == higher confidence. + if (mResults.isEmpty()) { + return 0; + } + + double mean = mResults.stream() + .map(CombinedResult::getScore) + .reduce(0.0, Double::sum) / mResults.size(); + + double stddev = Math.sqrt( + mResults.stream() + .map(result -> Math.pow(result.getScore() - mean, 2)) + .reduce(0.0, Double::sum) / mResults.size()); + + return 1 - stddev; + } + + void addResults(Collection<FalsingClassifier.Result> results, long uptimeMillis) { + double finalScore = 0; + for (FalsingClassifier.Result result : results) { + // A confidence of 1 adds either 0 for non-falsed or 1 for falsed. + // A confidence of 0 adds 0.5. + finalScore += (result.isFalse() ? .5 : -.5) * result.getConfidence() + 0.5; + } + + finalScore /= results.size(); + + //noinspection StatementWithEmptyBody + while (mResults.poll() != null) { + // Empty out the expired results. + } + + mResults.add(new CombinedResult(uptimeMillis, finalScore)); + } + + /** + * Represents a falsing score combing all the classifiers together. + * + * Can "decay" over time, such that older results contribute less. Once they drop below + * a certain threshold, the {@link #getDelay(TimeUnit)} method will return <= 0, indicating + * that this result can be discarded. + */ + private class CombinedResult implements Delayed { + + private final long mExpiryMs; + private final double mScore; + + CombinedResult(long uptimeMillis, double score) { + mExpiryMs = uptimeMillis + TOTAL_DECAY_TIME_MS; + mScore = score; + } + + double getDecayedScore(long nowMs) { + long remainingTimeMs = mExpiryMs - nowMs; + long decayedTimeMs = TOTAL_DECAY_TIME_MS - remainingTimeMs; + double timeIntervals = (double) decayedTimeMs / DECAY_INTERVAL_MS; + return mScore * Math.pow(HISTORY_DECAY, timeIntervals); + } + + double getScore() { + return mScore; + } + + @Override + public long getDelay(TimeUnit unit) { + return unit.convert(mExpiryMs - mSystemClock.uptimeMillis(), TimeUnit.MILLISECONDS); + } + + @Override + public int compareTo(Delayed o) { + long ourDelay = getDelay(TimeUnit.MILLISECONDS); + long otherDelay = o.getDelay(TimeUnit.MILLISECONDS); + return Long.compare(ourDelay, otherDelay); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java index 0565165e1e8d..cd399fe15de1 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java @@ -56,20 +56,21 @@ class PointerCountClassifier extends FalsingClassifier { } @Override - public boolean isFalseTouch() { + Result calculateFalsingResult(double historyPenalty, double historyConfidence) { int interactionType = getInteractionType(); - if (interactionType == QUICK_SETTINGS || interactionType == NOTIFICATION_DRAG_DOWN) { - return mMaxPointerCount > MAX_ALLOWED_POINTERS_SWIPE_DOWN; - } - return mMaxPointerCount > MAX_ALLOWED_POINTERS; + int allowedPointerCount = + (interactionType == QUICK_SETTINGS || interactionType == NOTIFICATION_DRAG_DOWN) + ? MAX_ALLOWED_POINTERS_SWIPE_DOWN : MAX_ALLOWED_POINTERS; + + return mMaxPointerCount > allowedPointerCount + ? Result.falsed(1, getReason(allowedPointerCount)) : Result.passed(0); } - @Override - String getReason() { + private String getReason(int allowedPointerCount) { return String.format( (Locale) null, "{pointersObserved=%d, threshold=%d}", mMaxPointerCount, - MAX_ALLOWED_POINTERS); + allowedPointerCount); } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java index 6e73fc06de4c..9ee85986c53c 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java @@ -33,7 +33,7 @@ import javax.inject.Inject; /** * False touch if proximity sensor is covered for more than a certain percentage of the gesture. * - * This classifer is essentially a no-op for QUICK_SETTINGS, as we assume the sensor may be + * This classifier is essentially a no-op for QUICK_SETTINGS, as we assume the sensor may be * covered when swiping from the top. */ class ProximityClassifier extends FalsingClassifier { @@ -112,28 +112,29 @@ class ProximityClassifier extends FalsingClassifier { } @Override - public boolean isFalseTouch() { + Result calculateFalsingResult(double historyPenalty, double historyConfidence) { if (getInteractionType() == QUICK_SETTINGS) { - return false; + return Result.passed(0); } logInfo("Percent of gesture in proximity: " + mPercentNear); if (mPercentNear > mPercentCoveredThreshold) { - return !mDistanceClassifier.isLongSwipe(); + Result longSwipeResult = mDistanceClassifier.isLongSwipe(); + return longSwipeResult.isFalse() + ? Result.falsed(0.5, getReason(longSwipeResult)) : Result.passed(0.5); } - return false; + return Result.passed(0.5); } - @Override - String getReason() { + private String getReason(Result longSwipeResult) { return String.format( (Locale) null, "{percentInProximity=%f, threshold=%f, distanceClassifier=%s}", mPercentNear, mPercentCoveredThreshold, - mDistanceClassifier.getReason()); + longSwipeResult.getReason()); } /** diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java index 6b7a1413bc74..f2622ec4e6e9 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java @@ -30,7 +30,6 @@ import javax.inject.Named; */ public class SingleTapClassifier extends FalsingClassifier { private final float mTouchSlop; - private String mReason; @Inject SingleTapClassifier(FalsingDataProvider dataProvider, @@ -40,36 +39,31 @@ public class SingleTapClassifier extends FalsingClassifier { } @Override - boolean isFalseTouch() { - return !isTap(getRecentMotionEvents()); + Result calculateFalsingResult(double historyPenalty, double historyConfidence) { + return isTap(getRecentMotionEvents()); } /** Given a list of {@link android.view.MotionEvent}'s, returns true if the look like a tap. */ - public boolean isTap(List<MotionEvent> motionEvents) { + public Result isTap(List<MotionEvent> motionEvents) { float downX = motionEvents.get(0).getX(); float downY = motionEvents.get(0).getY(); for (MotionEvent event : motionEvents) { + String reason; if (Math.abs(event.getX() - downX) >= mTouchSlop) { - mReason = "dX too big for a tap: " + reason = "dX too big for a tap: " + Math.abs(event.getX() - downX) + "vs " + mTouchSlop; - return false; + return Result.falsed(0.5, reason); } else if (Math.abs(event.getY() - downY) >= mTouchSlop) { - mReason = "dY too big for a tap: " + reason = "dY too big for a tap: " + Math.abs(event.getY() - downY) + "vs " + mTouchSlop; - return false; + return Result.falsed(0.5, reason); } } - mReason = ""; - return true; - } - - @Override - String getReason() { - return mReason; + return Result.passed(0); } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java index 711a0fc0f478..d470d6297170 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java @@ -38,32 +38,40 @@ public class TypeClassifier extends FalsingClassifier { } @Override - public boolean isFalseTouch() { + Result calculateFalsingResult(double historyPenalty, double historyConfidence) { boolean vertical = isVertical(); boolean up = isUp(); boolean right = isRight(); + boolean wrongDirection = true; switch (getInteractionType()) { case QUICK_SETTINGS: case PULSE_EXPAND: case NOTIFICATION_DRAG_DOWN: - return !vertical || up; + wrongDirection = !vertical || up; + break; case NOTIFICATION_DISMISS: - return vertical; + wrongDirection = vertical; + break; case UNLOCK: case BOUNCER_UNLOCK: - return !vertical || !up; + wrongDirection = !vertical || !up; + break; case LEFT_AFFORDANCE: // Swiping from the bottom left corner for camera or similar. - return !right || !up; + wrongDirection = !right || !up; + break; case RIGHT_AFFORDANCE: // Swiping from the bottom right corner for camera or similar. - return right || !up; + wrongDirection = right || !up; + break; default: - return true; + wrongDirection = true; + break; } + + return wrongDirection ? Result.falsed(1, getReason()) : Result.passed(0.5); } - @Override - String getReason() { + private String getReason() { return String.format("{vertical=%s, up=%s, right=%s}", isVertical(), isUp(), isRight()); } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java index 383dda498b49..2bfb2186191b 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java @@ -84,7 +84,7 @@ class ZigZagClassifier extends FalsingClassifier { } @Override - boolean isFalseTouch() { + Result calculateFalsingResult(double historyPenalty, double historyConfidence) { List<MotionEvent> motionEvents = getRecentMotionEvents(); // Rotate horizontal gestures to be horizontal between their first and last point. // Rotate vertical gestures to be vertical between their first and last point. @@ -95,7 +95,7 @@ class ZigZagClassifier extends FalsingClassifier { // For vertical lines, the difference in the y direction should be small. if (motionEvents.size() < 3) { - return false; + return Result.passed(0); } List<Point> rotatedPoints; @@ -155,11 +155,11 @@ class ZigZagClassifier extends FalsingClassifier { logDebug("Straightness Deviance: (" + devianceX + "," + devianceY + ") vs " + "(" + maxXDeviance + "," + maxYDeviance + ")"); - return devianceX > maxXDeviance || devianceY > maxYDeviance; + return devianceX > maxXDeviance || devianceY > maxYDeviance + ? Result.falsed(0.5, getReason()) : Result.passed(0.5); } - @Override - String getReason() { + private String getReason() { return String.format( (Locale) null, "{devianceX=%f, maxDevianceX=%s, devianceY=%s, maxDevianceY=%s}", diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt index 0e4f68431c16..9d92a40beec4 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt @@ -37,6 +37,7 @@ import android.service.controls.templates.ControlTemplate import android.service.controls.templates.RangeTemplate import android.service.controls.templates.StatelessTemplate import android.service.controls.templates.TemperatureControlTemplate +import android.service.controls.templates.ThumbnailTemplate import android.service.controls.templates.ToggleRangeTemplate import android.service.controls.templates.ToggleTemplate import android.util.MathUtils @@ -87,8 +88,11 @@ class ControlViewHolder( ): KClass<out Behavior> { return when { status != Control.STATUS_OK -> StatusBehavior::class - deviceType == DeviceTypes.TYPE_CAMERA -> TouchBehavior::class template == ControlTemplate.NO_TEMPLATE -> TouchBehavior::class + template is ThumbnailTemplate -> ThumbnailBehavior::class + + // Required for legacy support, or where cameras do not use the new template + deviceType == DeviceTypes.TYPE_CAMERA -> TouchBehavior::class template is ToggleTemplate -> ToggleBehavior::class template is StatelessTemplate -> TouchBehavior::class template is ToggleRangeTemplate -> ToggleRangeBehavior::class @@ -105,7 +109,7 @@ class ControlViewHolder( private var statusAnimator: Animator? = null private val baseLayer: GradientDrawable val icon: ImageView = layout.requireViewById(R.id.icon) - private val status: TextView = layout.requireViewById(R.id.status) + val status: TextView = layout.requireViewById(R.id.status) private var nextStatusText: CharSequence = "" val title: TextView = layout.requireViewById(R.id.title) val subtitle: TextView = layout.requireViewById(R.id.subtitle) @@ -132,7 +136,6 @@ class ControlViewHolder( val ld = layout.getBackground() as LayerDrawable ld.mutate() clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) as ClipDrawable - clipLayer.alpha = ALPHA_DISABLED baseLayer = ld.findDrawableByLayerId(R.id.background) as GradientDrawable // needed for marquee to start status.setSelected(true) @@ -315,7 +318,9 @@ class ControlViewHolder( ) } - (clipLayer.getDrawable() as GradientDrawable).apply { + clipLayer.getDrawable().apply { + clipLayer.alpha = ALPHA_DISABLED + val newBaseColor = if (behavior is ToggleRangeBehavior) { ColorUtils.blendARGB(bg, newClipColor, toggleBackgroundIntensity) } else { @@ -323,15 +328,25 @@ class ControlViewHolder( } stateAnimator?.cancel() if (animated) { - val oldColor = color?.defaultColor ?: newClipColor + val oldColor = if (this is GradientDrawable) { + this.color?.defaultColor ?: newClipColor + } else { + newClipColor + } val oldBaseColor = baseLayer.color?.defaultColor ?: newBaseColor val oldAlpha = layout.alpha + + // Animate both alpha and background colors. Only animate colors for + // GradientDrawables and not static images as used for the ThumbnailTemplate. stateAnimator = ValueAnimator.ofInt(clipLayer.alpha, newAlpha).apply { addUpdateListener { alpha = it.animatedValue as Int - setColor(ColorUtils.blendARGB(oldColor, newClipColor, it.animatedFraction)) - baseLayer.setColor(ColorUtils.blendARGB(oldBaseColor, - newBaseColor, it.animatedFraction)) + if (this is GradientDrawable) { + this.setColor(ColorUtils.blendARGB(oldColor, newClipColor, + it.animatedFraction)) + } + baseLayer.setColor(ColorUtils.blendARGB(oldBaseColor, newBaseColor, + it.animatedFraction)) layout.alpha = MathUtils.lerp(oldAlpha, 1f, it.animatedFraction) } addListener(object : AnimatorListenerAdapter() { @@ -345,7 +360,9 @@ class ControlViewHolder( } } else { alpha = newAlpha - setColor(newClipColor) + if (this is GradientDrawable) { + this.setColor(newClipColor) + } baseLayer.setColor(newBaseColor) layout.alpha = 1f } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt index 3f17a4fefd7e..ad2b785ea5c5 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt @@ -92,7 +92,9 @@ private val deviceColorMap = mapOf<Int, Pair<Int, Int>>( (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_COOL) to Pair(R.color.thermo_cool_foreground, R.color.control_enabled_thermo_cool_background), DeviceTypes.TYPE_LIGHT - to Pair(R.color.light_foreground, R.color.control_enabled_light_background) + to Pair(R.color.light_foreground, R.color.control_enabled_light_background), + DeviceTypes.TYPE_CAMERA + to Pair(R.color.camera_foreground, R.color.control_enabled_default_background) ).withDefault { Pair(R.color.control_foreground, R.color.control_enabled_default_background) } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt new file mode 100644 index 000000000000..c2168aa8d9d9 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.controls.ui + +import android.graphics.BlendMode +import android.graphics.BlendModeColorFilter +import android.graphics.drawable.ClipDrawable +import android.graphics.drawable.LayerDrawable +import android.view.View +import android.service.controls.Control +import android.service.controls.templates.ThumbnailTemplate +import android.util.TypedValue + +import com.android.systemui.R +import com.android.systemui.controls.ui.ControlViewHolder.Companion.MAX_LEVEL +import com.android.systemui.controls.ui.ControlViewHolder.Companion.MIN_LEVEL + +/** + * Supports display of static images on the background of the tile. When marked active, the title + * and subtitle will not be visible. To be used with {@link Thumbnailtemplate} only. + */ +class ThumbnailBehavior : Behavior { + lateinit var template: ThumbnailTemplate + lateinit var control: Control + lateinit var cvh: ControlViewHolder + private var shadowOffsetX: Float = 0f + private var shadowOffsetY: Float = 0f + private var shadowRadius: Float = 0f + private var shadowColor: Int = 0 + + private val enabled: Boolean + get() = template.isActive() + + override fun initialize(cvh: ControlViewHolder) { + this.cvh = cvh + + val outValue = TypedValue() + cvh.context.resources.getValue(R.dimen.controls_thumbnail_shadow_x, outValue, true) + shadowOffsetX = outValue.getFloat() + + cvh.context.resources.getValue(R.dimen.controls_thumbnail_shadow_y, outValue, true) + shadowOffsetY = outValue.getFloat() + + cvh.context.resources.getValue(R.dimen.controls_thumbnail_shadow_radius, outValue, true) + shadowRadius = outValue.getFloat() + + shadowColor = cvh.context.resources.getColor(R.color.control_thumbnail_shadow_color) + cvh.layout.setOnClickListener(View.OnClickListener() { + cvh.controlActionCoordinator.touch(cvh, template.getTemplateId(), control) + }) + } + + override fun bind(cws: ControlWithState, colorOffset: Int) { + this.control = cws.control!! + cvh.setStatusText(control.getStatusText()) + template = control.getControlTemplate() as ThumbnailTemplate + + val ld = cvh.layout.getBackground() as LayerDrawable + val clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) as ClipDrawable + + clipLayer.setLevel(if (enabled) MAX_LEVEL else MIN_LEVEL) + + if (template.isActive()) { + cvh.title.visibility = View.INVISIBLE + cvh.subtitle.visibility = View.INVISIBLE + cvh.status.setShadowLayer(shadowOffsetX, shadowOffsetY, shadowRadius, shadowColor) + + cvh.bgExecutor.execute { + val drawable = template.getThumbnail().loadDrawable(cvh.context) + cvh.uiExecutor.execute { + val radius = cvh.context.getResources() + .getDimensionPixelSize(R.dimen.control_corner_radius).toFloat() + clipLayer.setDrawable(CornerDrawable(drawable, radius)) + clipLayer.setColorFilter(BlendModeColorFilter(cvh.context.resources + .getColor(R.color.control_thumbnail_tint), BlendMode.LUMINOSITY)) + cvh.applyRenderInfo(enabled, colorOffset) + } + } + } else { + cvh.title.visibility = View.VISIBLE + cvh.subtitle.visibility = View.VISIBLE + cvh.status.setShadowLayer(0f, 0f, 0f, shadowColor) + } + + cvh.applyRenderInfo(enabled, colorOffset) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java index f470a6b55b76..c26cc4466c6d 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java @@ -298,6 +298,22 @@ public class DozeLog implements Dumpable { mLogger.logDozeSuppressed(suppressedState); } + /** + * Appends new AOD sreen brightness to logs + * @param brightness display brightness setting + */ + public void traceDozeScreenBrightness(int brightness) { + mLogger.logDozeScreenBrightness(brightness); + } + + /** + * Appends new AOD dimming scrim opacity to logs + * @param scrimOpacity + */ + public void traceSetAodDimmingScrim(float scrimOpacity) { + mLogger.logSetAodDimmingScrim((long) scrimOpacity); + } + private class SummaryStats { private int mCount; diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt index 0c9e14352946..fddefae6f5b6 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt @@ -226,6 +226,22 @@ class DozeLogger @Inject constructor( "Doze state suppressed, state=$str1" }) } + + fun logDozeScreenBrightness(brightness: Int) { + buffer.log(TAG, INFO, { + int1 = brightness + }, { + "Doze screen brightness set, brightness=$int1" + }) + } + + fun logSetAodDimmingScrim(scrimOpacity: Long) { + buffer.log(TAG, INFO, { + long1 = scrimOpacity + }, { + "Doze aod dimming scrim opacity set, opacity=$long1" + }) + } } private const val TAG = "DozeLog" diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index ebfce661c9af..c542e5b07d9b 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -34,6 +34,7 @@ import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; +import android.util.IndentingPrintWriter; import android.util.Log; import android.view.Display; @@ -79,6 +80,7 @@ public class DozeSensors { private long mDebounceFrom; private boolean mSettingRegistered; private boolean mListening; + private boolean mListeningTouchScreenSensors; @VisibleForTesting public enum DozeSensorsUiEvent implements UiEventLogger.UiEventEnum { @@ -232,22 +234,25 @@ public class DozeSensors { /** * If sensors should be registered and sending signals. */ - public void setListening(boolean listen) { - if (mListening == listen) { + public void setListening(boolean listen, boolean includeTouchScreenSensors) { + if (mListening == listen && mListeningTouchScreenSensors == includeTouchScreenSensors) { return; } mListening = listen; + mListeningTouchScreenSensors = includeTouchScreenSensors; updateListening(); } /** * Registers/unregisters sensors based on internal state. */ - public void updateListening() { + private void updateListening() { boolean anyListening = false; for (TriggerSensor s : mSensors) { - s.setListening(mListening); - if (mListening) { + boolean listen = mListening + && (!s.mRequiresTouchscreen || mListeningTouchScreenSensors); + s.setListening(listen); + if (listen) { anyListening = true; } } @@ -319,10 +324,14 @@ public class DozeSensors { /** Dump current state */ public void dump(PrintWriter pw) { + pw.println("mListening=" + mListening); + pw.println("mListeningTouchScreenSensors=" + mListeningTouchScreenSensors); + IndentingPrintWriter idpw = new IndentingPrintWriter(pw); + idpw.increaseIndent(); for (TriggerSensor s : mSensors) { - pw.println(" Sensor: " + s.toString()); + idpw.println("Sensor: " + s.toString()); } - pw.println(" ProxSensor: " + mProximitySensor.toString()); + idpw.println("ProxSensor: " + mProximitySensor.toString()); } /** diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index 6888d1ad6063..c617f3d751d0 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -29,6 +29,7 @@ import android.metrics.LogMaker; import android.os.SystemClock; import android.os.UserHandle; import android.text.format.Formatter; +import android.util.IndentingPrintWriter; import android.util.Log; import android.view.Display; @@ -434,15 +435,12 @@ public class DozeTriggers implements DozeMachine.Part { break; case DOZE_PULSE_DONE: mDozeSensors.requestTemporaryDisable(); - // A pulse will temporarily disable sensors that require a touch screen. - // Let's make sure that they are re-enabled when the pulse is over. - mDozeSensors.updateListening(); break; case FINISH: mBroadcastReceiver.unregister(mBroadcastDispatcher); mDozeHost.removeCallback(mHostCallback); mDockManager.removeListener(mDockEventListener); - mDozeSensors.setListening(false); + mDozeSensors.setListening(false, false); mDozeSensors.setProxListening(false); mWantSensors = false; mWantProx = false; @@ -450,20 +448,16 @@ public class DozeTriggers implements DozeMachine.Part { break; default: } + mDozeSensors.setListening(mWantSensors, mWantTouchScreenSensors); } @Override public void onScreenState(int state) { mDozeSensors.onScreenState(state); - if (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND - || state == Display.STATE_OFF) { - mDozeSensors.setProxListening(mWantProx); - mDozeSensors.setListening(mWantSensors); - mDozeSensors.setTouchscreenSensorsListening(mWantTouchScreenSensors); - } else { - mDozeSensors.setProxListening(false); - mDozeSensors.setListening(mWantSensors); - } + mDozeSensors.setProxListening(mWantProx && (state == Display.STATE_DOZE + || state == Display.STATE_DOZE_SUSPEND + || state == Display.STATE_OFF)); + mDozeSensors.setListening(mWantSensors, mWantTouchScreenSensors); } private void checkTriggersAtInit() { @@ -539,7 +533,9 @@ public class DozeTriggers implements DozeMachine.Part { pw.println(" pulsePending=" + mPulsePending); pw.println("DozeSensors:"); - mDozeSensors.dump(pw); + IndentingPrintWriter idpw = new IndentingPrintWriter(pw); + idpw.increaseIndent(); + mDozeSensors.dump(idpw); } private class TriggerReceiver extends BroadcastReceiver { diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index 9c90510099a2..ad4c44767995 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -50,6 +50,7 @@ import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.UserInfo; import android.content.res.ColorStateList; +import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.Color; @@ -256,6 +257,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, private UserContextProvider mUserContextProvider; @VisibleForTesting boolean mShowLockScreenCardsAndControls = false; + private int mSmallestScreenWidthDp; @VisibleForTesting public enum GlobalActionsEvent implements UiEventLogger.UiEventEnum { @@ -344,6 +346,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, mSysUiState = sysUiState; mMainHandler = handler; mUserContextProvider = userContextProvider; + mSmallestScreenWidthDp = mContext.getResources().getConfiguration().smallestScreenWidthDp; // receive broadcasts IntentFilter filter = new IntentFilter(); @@ -760,6 +763,15 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, } } + @Override + public void onConfigChanged(Configuration newConfig) { + if (mDialog != null && mDialog.isShowing() + && (newConfig.smallestScreenWidthDp != mSmallestScreenWidthDp)) { + mSmallestScreenWidthDp = newConfig.smallestScreenWidthDp; + mDialog.refreshDialog(); + } + } + public void destroy() { mConfigurationController.removeCallback(this); } @@ -2230,6 +2242,9 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, return; } + boolean isLandscapeWalletViewShown = mContext.getResources().getBoolean( + com.android.systemui.R.bool.global_actions_show_landscape_wallet_view); + int rotation = RotationUtils.getRotation(mContext); boolean rotationLocked = RotationPolicy.isRotationLocked(mContext); if (rotation != RotationUtils.ROTATION_NONE) { @@ -2246,6 +2261,10 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, mGlobalActionsLayout.post(() -> RotationPolicy.setRotationLockAtAngle( mContext, false, RotationUtils.ROTATION_NONE)); + + if (!isLandscapeWalletViewShown) { + return; + } } } else { if (!rotationLocked) { @@ -2253,44 +2272,48 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, mResetOrientationData = new ResetOrientationData(); mResetOrientationData.locked = false; } + } - // Lock to portrait, so the user doesn't accidentally hide the panel. + boolean shouldLockRotation = !isLandscapeWalletViewShown; + if (rotationLocked != shouldLockRotation) { + // Locks the screen to portrait if the landscape / seascape orientation does not + // show the wallet view, so the user doesn't accidentally hide the panel. // This call is posted so that the rotation does not change until post-layout, // otherwise onConfigurationChanged() may not get invoked. mGlobalActionsLayout.post(() -> RotationPolicy.setRotationLockAtAngle( - mContext, true, RotationUtils.ROTATION_NONE)); + mContext, shouldLockRotation, RotationUtils.ROTATION_NONE)); } + } - // Disable rotation suggestions, if enabled - setRotationSuggestionsEnabled(false); - - FrameLayout panelContainer = - findViewById(com.android.systemui.R.id.global_actions_wallet); - FrameLayout.LayoutParams panelParams = - new FrameLayout.LayoutParams( - FrameLayout.LayoutParams.MATCH_PARENT, - FrameLayout.LayoutParams.MATCH_PARENT); - if (!mControlsAvailable) { - panelParams.topMargin = mContext.getResources().getDimensionPixelSize( - com.android.systemui.R.dimen.global_actions_wallet_top_margin); - } - View walletView = mWalletViewController.getPanelContent(); - panelContainer.addView(walletView, panelParams); - // Smooth transitions when wallet is resized, which can happen when a card is added - ViewGroup root = findViewById(com.android.systemui.R.id.global_actions_grid_root); - if (root != null) { - walletView.addOnLayoutChangeListener((v, l, t, r, b, ol, ot, or, ob) -> { - int oldHeight = ob - ot; - int newHeight = b - t; - if (oldHeight > 0 && oldHeight != newHeight) { - TransitionSet transition = new AutoTransition() - .setDuration(250) - .setOrdering(TransitionSet.ORDERING_TOGETHER); - TransitionManager.beginDelayedTransition(root, transition); - } - }); - } + // Disable rotation suggestions, if enabled + setRotationSuggestionsEnabled(false); + + FrameLayout panelContainer = + findViewById(com.android.systemui.R.id.global_actions_wallet); + FrameLayout.LayoutParams panelParams = + new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.MATCH_PARENT); + if (!mControlsAvailable) { + panelParams.topMargin = mContext.getResources().getDimensionPixelSize( + com.android.systemui.R.dimen.global_actions_wallet_top_margin); + } + View walletView = mWalletViewController.getPanelContent(); + panelContainer.addView(walletView, panelParams); + // Smooth transitions when wallet is resized, which can happen when a card is added + ViewGroup root = findViewById(com.android.systemui.R.id.global_actions_grid_root); + if (root != null) { + walletView.addOnLayoutChangeListener((v, l, t, r, b, ol, ot, or, ob) -> { + int oldHeight = ob - ot; + int newHeight = b - t; + if (oldHeight > 0 && oldHeight != newHeight) { + TransitionSet transition = new AutoTransition() + .setDuration(250) + .setOrdering(TransitionSet.ORDERING_TOGETHER); + TransitionManager.beginDelayedTransition(root, transition); + } + }); } } diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java index a330be6449e2..ce5795ccd339 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java @@ -103,7 +103,7 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks d.setOnShowListener(dialog -> { if (mBlurUtils.supportsBlursOnWindows()) { - background.setAlpha((int) (ScrimController.BLUR_SCRIM_ALPHA * 255)); + background.setAlpha((int) (ScrimController.BUSY_SCRIM_ALPHA * 255)); mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(), mBlurUtils.blurRadiusOfRatio(1)); } else { diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java index 451bd42bd053..eb86128a82a5 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -37,6 +37,7 @@ import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.core.graphics.drawable.IconCompat; +import com.android.internal.logging.UiEventLogger; import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.Utils; import com.android.settingslib.bluetooth.BluetoothUtils; @@ -84,11 +85,14 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { @VisibleForTesting LocalMediaManager mLocalMediaManager; + private MediaOutputMetricLogger mMetricLogger; + private UiEventLogger mUiEventLogger; + @Inject public MediaOutputController(@NonNull Context context, String packageName, boolean aboveStatusbar, MediaSessionManager mediaSessionManager, LocalBluetoothManager lbm, ShadeController shadeController, ActivityStarter starter, - NotificationEntryManager notificationEntryManager) { + NotificationEntryManager notificationEntryManager, UiEventLogger uiEventLogger) { mContext = context; mPackageName = packageName; mMediaSessionManager = mediaSessionManager; @@ -98,6 +102,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { mNotificationEntryManager = notificationEntryManager; InfoMediaManager imm = new InfoMediaManager(mContext, packageName, null, lbm); mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName); + mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName); + mUiEventLogger = uiEventLogger; } void start(@NonNull Callback cb) { @@ -151,6 +157,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { public void onSelectedDeviceStateChanged(MediaDevice device, @LocalMediaManager.MediaDeviceState int state) { mCallback.onRouteChanged(); + mMetricLogger.logOutputSuccess(device.toString(), mMediaDevices); } @Override @@ -161,6 +168,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { @Override public void onRequestFailed(int reason) { mCallback.onRouteChanged(); + mMetricLogger.logOutputFailure(mMediaDevices, reason); } CharSequence getHeaderTitle() { @@ -311,6 +319,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { } void connectDevice(MediaDevice device) { + mMetricLogger.updateOutputEndPoints(getCurrentConnectedMediaDevice(), device); + ThreadUtils.postOnBackgroundThread(() -> { mLocalMediaManager.connectDevice(device); }); @@ -439,7 +449,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { void launchMediaOutputDialog() { mCallback.dismissDialog(); - new MediaOutputDialog(mContext, mAboveStatusbar, this); + new MediaOutputDialog(mContext, mAboveStatusbar, this, mUiEventLogger); } void launchMediaOutputGroupDialog() { diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java index a892a12f387b..53029bd04ef6 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java @@ -23,6 +23,9 @@ import android.view.WindowManager; import androidx.core.graphics.drawable.IconCompat; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.logging.UiEvent; +import com.android.internal.logging.UiEventLogger; import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; @@ -31,10 +34,12 @@ import com.android.systemui.dagger.SysUISingleton; */ @SysUISingleton public class MediaOutputDialog extends MediaOutputBaseDialog { + final UiEventLogger mUiEventLogger; MediaOutputDialog(Context context, boolean aboveStatusbar, MediaOutputController - mediaOutputController) { + mediaOutputController, UiEventLogger uiEventLogger) { super(context, mediaOutputController); + mUiEventLogger = uiEventLogger; mAdapter = new MediaOutputAdapter(mMediaOutputController); if (!aboveStatusbar) { getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); @@ -45,6 +50,7 @@ public class MediaOutputDialog extends MediaOutputBaseDialog { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + mUiEventLogger.log(MediaOutputEvent.MEDIA_OUTPUT_DIALOG_SHOW); } @Override @@ -78,4 +84,21 @@ public class MediaOutputDialog extends MediaOutputBaseDialog { return mMediaOutputController.isActiveRemoteDevice( mMediaOutputController.getCurrentConnectedMediaDevice()) ? View.VISIBLE : View.GONE; } + + @VisibleForTesting + public enum MediaOutputEvent implements UiEventLogger.UiEventEnum { + @UiEvent(doc = "The MediaOutput dialog became visible on the screen.") + MEDIA_OUTPUT_DIALOG_SHOW(655); + + private final int mId; + + MediaOutputEvent(int id) { + mId = id; + } + + @Override + public int getId() { + return mId; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt index 7d1a7ced7472..0f340a5cedaa 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt @@ -18,6 +18,7 @@ package com.android.systemui.media.dialog import android.content.Context import android.media.session.MediaSessionManager +import com.android.internal.logging.UiEventLogger import com.android.settingslib.bluetooth.LocalBluetoothManager import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.notification.NotificationEntryManager @@ -33,7 +34,8 @@ class MediaOutputDialogFactory @Inject constructor( private val lbm: LocalBluetoothManager?, private val shadeController: ShadeController, private val starter: ActivityStarter, - private val notificationEntryManager: NotificationEntryManager + private val notificationEntryManager: NotificationEntryManager, + private val uiEventLogger: UiEventLogger ) { companion object { var mediaOutputDialog: MediaOutputDialog? = null @@ -43,8 +45,10 @@ class MediaOutputDialogFactory @Inject constructor( fun create(packageName: String, aboveStatusBar: Boolean) { mediaOutputDialog?.dismiss() mediaOutputDialog = MediaOutputController(context, packageName, aboveStatusBar, - mediaSessionManager, lbm, shadeController, starter, notificationEntryManager).run { - MediaOutputDialog(context, aboveStatusBar, this) } + mediaSessionManager, lbm, shadeController, starter, notificationEntryManager, + uiEventLogger).run { + MediaOutputDialog(context, aboveStatusBar, this, uiEventLogger) + } } /** dismiss [MediaOutputDialog] if exist. */ diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java new file mode 100644 index 000000000000..ac0295ed6d14 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.dialog; + +import static android.media.MediaRoute2ProviderService.REASON_INVALID_COMMAND; +import static android.media.MediaRoute2ProviderService.REASON_NETWORK_ERROR; +import static android.media.MediaRoute2ProviderService.REASON_REJECTED; +import static android.media.MediaRoute2ProviderService.REASON_ROUTE_NOT_AVAILABLE; +import static android.media.MediaRoute2ProviderService.REASON_UNKNOWN_ERROR; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.util.Log; + +import com.android.settingslib.media.MediaDevice; +import com.android.systemui.shared.system.SysUiStatsLog; + +import java.util.List; + +/** + * Metric logger for media output features + */ +public class MediaOutputMetricLogger { + + private static final String TAG = "MediaOutputMetricLogger"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + private final Context mContext; + private final String mPackageName; + private MediaDevice mSourceDevice, mTargetDevice; + private int mWiredDeviceCount; + private int mConnectedBluetoothDeviceCount; + private int mRemoteDeviceCount; + private int mAppliedDeviceCountWithinRemoteGroup; + + public MediaOutputMetricLogger(Context context, String packageName) { + mContext = context; + mPackageName = packageName; + } + + /** + * Update the endpoints of a content switching operation. + * This method should be called before a switching operation, so the metric logger can track + * source and target devices. + * @param source the current connected media device + * @param target the target media device for content switching to + */ + public void updateOutputEndPoints(MediaDevice source, MediaDevice target) { + mSourceDevice = source; + mTargetDevice = target; + + if (DEBUG) { + Log.d(TAG, "updateOutputEndPoints -" + + " source:" + mSourceDevice.toString() + + " target:" + mTargetDevice.toString()); + } + } + + /** + * Do the metric logging of content switching success. + * @param selectedDeviceType string representation of the target media device + * @param deviceList media device list for device count updating + */ + public void logOutputSuccess(String selectedDeviceType, List<MediaDevice> deviceList) { + if (DEBUG) { + Log.d(TAG, "logOutputSuccess - selected device: " + selectedDeviceType); + } + + updateLoggingDeviceCount(deviceList); + + SysUiStatsLog.write( + SysUiStatsLog.MEDIAOUTPUT_OP_SWITCH_REPORTED, + getLoggingDeviceType(mSourceDevice, true), + getLoggingDeviceType(mTargetDevice, false), + SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__RESULT__OK, + SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__NO_ERROR, + getLoggingPackageName(), + mWiredDeviceCount, + mConnectedBluetoothDeviceCount, + mRemoteDeviceCount, + mAppliedDeviceCountWithinRemoteGroup); + } + + /** + * Do the metric logging of content switching failure. + * @param deviceList media device list for device count updating + * @param reason the reason of content switching failure + */ + public void logOutputFailure(List<MediaDevice> deviceList, int reason) { + if (DEBUG) { + Log.e(TAG, "logRequestFailed - " + reason); + } + + updateLoggingDeviceCount(deviceList); + + SysUiStatsLog.write( + SysUiStatsLog.MEDIAOUTPUT_OP_SWITCH_REPORTED, + getLoggingDeviceType(mSourceDevice, true), + getLoggingDeviceType(mTargetDevice, false), + SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__RESULT__ERROR, + getLoggingSwitchOpSubResult(reason), + getLoggingPackageName(), + mWiredDeviceCount, + mConnectedBluetoothDeviceCount, + mRemoteDeviceCount, + mAppliedDeviceCountWithinRemoteGroup); + } + + private void updateLoggingDeviceCount(List<MediaDevice> deviceList) { + mWiredDeviceCount = mConnectedBluetoothDeviceCount = mRemoteDeviceCount = 0; + mAppliedDeviceCountWithinRemoteGroup = 0; + + for (MediaDevice mediaDevice : deviceList) { + if (mediaDevice.isConnected()) { + switch (mediaDevice.getDeviceType()) { + case MediaDevice.MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE: + case MediaDevice.MediaDeviceType.TYPE_USB_C_AUDIO_DEVICE: + mWiredDeviceCount++; + break; + case MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE: + mConnectedBluetoothDeviceCount++; + break; + case MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE: + case MediaDevice.MediaDeviceType.TYPE_CAST_GROUP_DEVICE: + mRemoteDeviceCount++; + break; + default: + } + } + } + + if (DEBUG) { + Log.d(TAG, "connected devices:" + " wired: " + mWiredDeviceCount + + " bluetooth: " + mConnectedBluetoothDeviceCount + + " remote: " + mRemoteDeviceCount); + } + } + + private int getLoggingDeviceType(MediaDevice device, boolean isSourceDevice) { + switch (device.getDeviceType()) { + case MediaDevice.MediaDeviceType.TYPE_PHONE_DEVICE: + return isSourceDevice + ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__BUILTIN_SPEAKER + : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__BUILTIN_SPEAKER; + case MediaDevice.MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE: + return isSourceDevice + ? SysUiStatsLog + .MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__WIRED_3POINT5_MM_AUDIO + : SysUiStatsLog + .MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__WIRED_3POINT5_MM_AUDIO; + case MediaDevice.MediaDeviceType.TYPE_USB_C_AUDIO_DEVICE: + return isSourceDevice + ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__USB_C_AUDIO + : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__USB_C_AUDIO; + case MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE: + return isSourceDevice + ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__BLUETOOTH + : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__BLUETOOTH; + case MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE: + return isSourceDevice + ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__REMOTE_SINGLE + : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__REMOTE_SINGLE; + case MediaDevice.MediaDeviceType.TYPE_CAST_GROUP_DEVICE: + return isSourceDevice + ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__REMOTE_GROUP + : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__REMOTE_GROUP; + default: + return isSourceDevice + ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__UNKNOWN_TYPE + : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__UNKNOWN_TYPE; + } + } + + private int getLoggingSwitchOpSubResult(int reason) { + switch (reason) { + case REASON_REJECTED: + return SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__REJECTED; + case REASON_NETWORK_ERROR: + return SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__NETWORK_ERROR; + case REASON_ROUTE_NOT_AVAILABLE: + return SysUiStatsLog + .MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__ROUTE_NOT_AVAILABLE; + case REASON_INVALID_COMMAND: + return SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__INVALID_COMMAND; + case REASON_UNKNOWN_ERROR: + default: + return SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__UNKNOWN_ERROR; + } + } + + private String getLoggingPackageName() { + if (mPackageName != null && !mPackageName.isEmpty()) { + try { + final ApplicationInfo applicationInfo = mContext.getPackageManager() + .getApplicationInfo(mPackageName, /* default flag */ 0); + if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 + || (applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) { + return mPackageName; + } + } catch (Exception ex) { + Log.e(TAG, mPackageName + " is invalid."); + } + } + + return ""; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java index 5cd3b33a1b5f..4a633c320999 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java @@ -16,19 +16,30 @@ package com.android.systemui.people; +import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID; +import static android.appwidget.AppWidgetManager.INVALID_APPWIDGET_ID; + import android.app.Activity; import android.app.INotificationManager; import android.app.people.IPeopleManager; import android.app.people.PeopleSpaceTile; +import android.appwidget.AppWidgetManager; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.LauncherApps; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.ServiceManager; +import android.provider.Settings; import android.util.Log; import android.view.ViewGroup; +import androidx.preference.PreferenceManager; + import com.android.systemui.R; +import com.android.systemui.people.widget.PeopleSpaceWidgetProvider; import java.util.List; import java.util.Map; @@ -46,6 +57,9 @@ public class PeopleSpaceActivity extends Activity { private PackageManager mPackageManager; private LauncherApps mLauncherApps; private Context mContext; + private AppWidgetManager mAppWidgetManager; + private int mAppWidgetId; + private boolean mShowSingleConversation; @Override protected void onCreate(Bundle savedInstanceState) { @@ -59,7 +73,18 @@ public class PeopleSpaceActivity extends Activity { mPeopleManager = IPeopleManager.Stub.asInterface( ServiceManager.getService(Context.PEOPLE_SERVICE)); mLauncherApps = mContext.getSystemService(LauncherApps.class); + mAppWidgetManager = AppWidgetManager.getInstance(mContext); setTileViewsWithPriorityConversations(); + mAppWidgetId = getIntent().getIntExtra(EXTRA_APPWIDGET_ID, + INVALID_APPWIDGET_ID); + mShowSingleConversation = Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0; + // Finish the configuration activity immediately if a widget is added for multiple + // conversations. If the mAppWidgetId is INVALID, then the activity wasn't launched as a + // widget configuration activity. + if (!mShowSingleConversation && mAppWidgetId != INVALID_APPWIDGET_ID) { + finishActivity(); + } } /** @@ -93,12 +118,39 @@ public class PeopleSpaceActivity extends Activity { tileView.setName(tile.getUserName().toString()); tileView.setPackageIcon(mPackageManager.getApplicationIcon(pkg)); tileView.setPersonIcon(tile.getUserIcon()); - tileView.setOnClickListener(mLauncherApps, tile); + tileView.setOnClickListener(v -> storeWidgetConfiguration(tile)); } catch (Exception e) { Log.e(TAG, "Couldn't retrieve shortcut information", e); } } + /** Stores the user selected configuration for {@code mAppWidgetId}. */ + private void storeWidgetConfiguration(PeopleSpaceTile tile) { + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext); + SharedPreferences.Editor editor = sp.edit(); + if (PeopleSpaceUtils.DEBUG) { + Log.d(TAG, "Put " + tile.getUserName() + "'s shortcut ID: " + + tile.getId() + " for widget ID: " + + mAppWidgetId); + } + editor.putString(String.valueOf(mAppWidgetId), tile.getId()); + editor.commit(); + AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext); + int[] widgetIds = appWidgetManager.getAppWidgetIds( + new ComponentName(mContext, PeopleSpaceWidgetProvider.class)); + PeopleSpaceUtils.updateSingleConversationWidgets(mContext, widgetIds, mAppWidgetManager, + mNotificationManager); + finishActivity(); + } + + /** Finish activity with a successful widget configuration result. */ + private void finishActivity() { + Intent resultValue = new Intent(); + resultValue.putExtra(EXTRA_APPWIDGET_ID, mAppWidgetId); + setResult(RESULT_OK, resultValue); + finish(); + } + @Override protected void onResume() { super.onResume(); diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceTileView.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceTileView.java index 4aea5b8d6446..9ae7847031aa 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceTileView.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceTileView.java @@ -84,4 +84,9 @@ public class PeopleSpaceTileView extends LinearLayout { launcherApps.startShortcut(tile.getPackageName(), tile.getId(), null, null, UserHandle.getUserHandleForUid(tile.getUid()))); } + + /** Sets the click listener of the tile directly. */ + public void setOnClickListener(OnClickListener onClickListener) { + mTileView.setOnClickListener(onClickListener); + } } diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java index fe262b446a3c..dddd39b17209 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java @@ -17,11 +17,17 @@ package com.android.systemui.people; import android.app.INotificationManager; +import android.app.PendingIntent; import android.app.people.ConversationChannel; import android.app.people.IPeopleManager; import android.app.people.PeopleSpaceTile; +import android.appwidget.AppWidgetHost; +import android.appwidget.AppWidgetManager; import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.LauncherApps; +import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; @@ -29,17 +35,24 @@ import android.graphics.drawable.Drawable; import android.icu.text.MeasureFormat; import android.icu.util.Measure; import android.icu.util.MeasureUnit; +import android.os.ServiceManager; import android.os.UserHandle; import android.provider.Settings; import android.service.notification.ConversationChannelWrapper; import android.util.Log; +import android.widget.RemoteViews; + +import androidx.preference.PreferenceManager; import com.android.systemui.R; +import com.android.systemui.people.widget.LaunchConversationActivity; +import com.android.systemui.people.widget.PeopleSpaceWidgetProvider; import java.time.Duration; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -57,14 +70,15 @@ public class PeopleSpaceUtils { Context context, INotificationManager notificationManager, IPeopleManager peopleManager, LauncherApps launcherApps) throws Exception { - boolean showAllConversations = Settings.Global.getInt(context.getContentResolver(), - Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0; + boolean showOnlyPriority = Settings.Global.getInt(context.getContentResolver(), + Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 1; List<ConversationChannelWrapper> conversations = notificationManager.getConversations( true).getList(); List<Map.Entry<Long, PeopleSpaceTile>> tiles = getSortedTiles(peopleManager, conversations.stream().map(c -> new PeopleSpaceTile.Builder(c.getShortcutInfo(), launcherApps).build())); - if (showAllConversations) { + if (!showOnlyPriority) { + if (DEBUG) Log.d(TAG, "Add recent conversations"); List<ConversationChannel> recentConversations = peopleManager.getRecentConversations().getList(); List<Map.Entry<Long, PeopleSpaceTile>> recentTiles = @@ -77,6 +91,79 @@ public class PeopleSpaceUtils { return tiles; } + /** Updates {@code appWidgetIds} with their associated conversation stored. */ + public static void updateSingleConversationWidgets(Context context, int[] appWidgetIds, + AppWidgetManager appWidgetManager, INotificationManager notificationManager) { + PackageManager mPackageManager = context.getPackageManager(); + IPeopleManager mPeopleManager = IPeopleManager.Stub.asInterface( + ServiceManager.getService(Context.PEOPLE_SERVICE)); + LauncherApps mLauncherApps = context.getSystemService(LauncherApps.class); + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); + Intent activityIntent = new Intent(context, LaunchConversationActivity.class); + activityIntent.addFlags( + Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_CLEAR_TASK + | Intent.FLAG_ACTIVITY_NO_HISTORY + | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + try { + List<Map.Entry<Long, PeopleSpaceTile>> shortcutInfos = + PeopleSpaceUtils.getTiles( + context, notificationManager, + mPeopleManager, mLauncherApps); + for (int appWidgetId : appWidgetIds) { + String shortcutId = sp.getString(String.valueOf(appWidgetId), null); + if (DEBUG) { + Log.d(TAG, "Set widget: " + appWidgetId + " with shortcut ID: " + shortcutId); + } + + Optional<Map.Entry<Long, PeopleSpaceTile>> entry = shortcutInfos.stream().filter( + e -> e.getValue().getId().equals(shortcutId)).findFirst(); + if (!entry.isPresent() || shortcutId == null) { + if (DEBUG) Log.d(TAG, "Matching conversation not found for shortcut ID"); + AppWidgetHost host = new AppWidgetHost(context, 0); + host.deleteAppWidgetId(appWidgetId); + continue; + } + PeopleSpaceTile tile = entry.get().getValue(); + RemoteViews views = new RemoteViews(context.getPackageName(), + getLayout(tile)); + + String status = PeopleSpaceUtils.getLastInteractionString(context, + entry.get().getKey()); + views.setTextViewText(R.id.status, status); + views.setTextViewText(R.id.name, tile.getUserName().toString()); + + activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, tile.getId()); + activityIntent.putExtra( + PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, tile.getPackageName()); + activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_UID, tile.getUid()); + views.setOnClickPendingIntent(R.id.item, PendingIntent.getActivity( + context, + appWidgetId, + activityIntent, + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE)); + + views.setImageViewBitmap( + R.id.package_icon, + PeopleSpaceUtils.convertDrawableToBitmap( + mPackageManager.getApplicationIcon(tile.getPackageName()) + ) + ); + views.setImageViewIcon(R.id.person_icon, tile.getUserIcon()); + // Tell the AppWidgetManager to perform an update on the current app widget. + appWidgetManager.updateAppWidget(appWidgetId, views); + } + } catch (Exception e) { + Log.e(TAG, "Failed to retrieve conversations to set tiles"); + } + } + + /** Returns the layout ID for the {@code tile}. */ + private static int getLayout(PeopleSpaceTile tile) { + return tile.getNotification() == null ? R.layout.people_space_large_avatar_tile : + R.layout.people_space_small_avatar_tile; + } + /** Returns a list sorted by ascending last interaction time from {@code stream}. */ private static List<Map.Entry<Long, PeopleSpaceTile>> getSortedTiles( IPeopleManager peopleManager, Stream<PeopleSpaceTile> stream) { diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java index 9b7cf6e85ada..ac32e193d9f6 100644 --- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java +++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java @@ -16,11 +16,14 @@ package com.android.systemui.people.widget; +import android.app.INotificationManager; import android.app.NotificationChannel; +import android.appwidget.AppWidgetManager; import android.content.ComponentName; import android.content.Context; import android.os.ServiceManager; import android.os.UserHandle; +import android.provider.Settings; import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; import android.util.Log; @@ -42,13 +45,18 @@ public class PeopleSpaceWidgetManager { private static final boolean DEBUG = PeopleSpaceUtils.DEBUG; private final Context mContext; - private IAppWidgetService mAppWidgetManager; + private IAppWidgetService mAppWidgetService; + private AppWidgetManager mAppWidgetManager; + private INotificationManager mNotificationManager; @Inject public PeopleSpaceWidgetManager(Context context, IAppWidgetService appWidgetService) { if (DEBUG) Log.d(TAG, "constructor"); mContext = context; - mAppWidgetManager = appWidgetService; + mAppWidgetService = appWidgetService; + mAppWidgetManager = AppWidgetManager.getInstance(context); + mNotificationManager = INotificationManager.Stub.asInterface( + ServiceManager.getService(Context.NOTIFICATION_SERVICE)); } /** Constructor used for testing. */ @@ -56,21 +64,24 @@ public class PeopleSpaceWidgetManager { protected PeopleSpaceWidgetManager(Context context) { if (DEBUG) Log.d(TAG, "constructor"); mContext = context; - mAppWidgetManager = IAppWidgetService.Stub.asInterface( + mAppWidgetService = IAppWidgetService.Stub.asInterface( ServiceManager.getService(Context.APPWIDGET_SERVICE)); } /** AppWidgetManager setter used for testing. */ @VisibleForTesting - protected void setAppWidgetManager(IAppWidgetService appWidgetService) { - mAppWidgetManager = appWidgetService; + protected void setAppWidgetManager(IAppWidgetService appWidgetService, + AppWidgetManager appWidgetManager, INotificationManager notificationManager) { + mAppWidgetService = appWidgetService; + mAppWidgetManager = appWidgetManager; + mNotificationManager = notificationManager; } /** Updates People Space widgets. */ public void updateWidgets() { try { if (DEBUG) Log.d(TAG, "updateWidgets called"); - int[] widgetIds = mAppWidgetManager.getAppWidgetIds( + int[] widgetIds = mAppWidgetService.getAppWidgetIds( new ComponentName(mContext, PeopleSpaceWidgetProvider.class) ); @@ -80,9 +91,16 @@ public class PeopleSpaceWidgetManager { } if (DEBUG) Log.d(TAG, "updating " + widgetIds.length + " widgets"); - mAppWidgetManager - .notifyAppWidgetViewDataChanged(mContext.getOpPackageName(), widgetIds, - R.id.widget_list_view); + boolean showSingleConversation = Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0; + if (showSingleConversation) { + PeopleSpaceUtils.updateSingleConversationWidgets(mContext, widgetIds, + mAppWidgetManager, mNotificationManager); + } else { + mAppWidgetService + .notifyAppWidgetViewDataChanged(mContext.getOpPackageName(), widgetIds, + R.id.widget_list_view); + } } catch (Exception e) { Log.e(TAG, "Exception: " + e); } @@ -125,7 +143,8 @@ public class PeopleSpaceWidgetManager { @Override public void onNotificationRankingUpdate( - NotificationListenerService.RankingMap rankingMap) { } + NotificationListenerService.RankingMap rankingMap) { + } @Override public void onNotificationsInitialized() { diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java index 9f84514f8c47..1ee9e0ea728d 100644 --- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java +++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java @@ -16,11 +16,14 @@ package com.android.systemui.people.widget; +import android.app.INotificationManager; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.Context; import android.content.Intent; +import android.os.ServiceManager; +import android.provider.Settings; import android.util.Log; import android.widget.RemoteViews; @@ -41,6 +44,14 @@ public class PeopleSpaceWidgetProvider extends AppWidgetProvider { super.onUpdate(context, appWidgetManager, appWidgetIds); if (DEBUG) Log.d(TAG, "onUpdate called"); + boolean showSingleConversation = Settings.Global.getInt(context.getContentResolver(), + Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0; + if (showSingleConversation) { + PeopleSpaceUtils.updateSingleConversationWidgets(context, appWidgetIds, + appWidgetManager, INotificationManager.Stub.asInterface( + ServiceManager.getService(Context.NOTIFICATION_SERVICE))); + return; + } // Perform this loop procedure for each App Widget that belongs to this provider for (int appWidgetId : appWidgetIds) { RemoteViews views = diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt index 87ffbd465109..b2c2aa309811 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt @@ -262,8 +262,11 @@ class PrivacyItemController @Inject constructor( privacyList = emptyList() return } - val list = currentUserIds.flatMap { appOpsController.getActiveAppOpsForUser(it) } - .mapNotNull { toPrivacyItem(it) }.distinct() + val list = appOpsController.getActiveAppOpsForUser(UserHandle.USER_ALL).filter { + UserHandle.getUserId(it.uid) in currentUserIds || + it.code == AppOpsManager.OP_PHONE_CALL_MICROPHONE || + it.code == AppOpsManager.OP_PHONE_CALL_CAMERA + }.mapNotNull { toPrivacyItem(it) }.distinct() logger.logUpdatedPrivacyItemsList( list.joinToString(separator = ", ", transform = PrivacyItem::toLog)) privacyList = list diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java index 5afe526be918..386638217110 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java @@ -143,8 +143,6 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen } public void showDeviceMonitoringDialog() { - mHost.collapsePanels(); - // TODO: Delay dialog creation until after panels are collapsed. createDialog(); } @@ -291,6 +289,7 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen if (which == DialogInterface.BUTTON_NEGATIVE) { final Intent intent = new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS); mDialog.dismiss(); + // This dismisses the shade on opening the activity mActivityStarter.postStartActivityDismissingKeyguard(intent, 0); } } @@ -605,6 +604,7 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen public void onClick(View widget) { final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS); mDialog.dismiss(); + // This dismisses the shade on opening the activity mActivityStarter.postStartActivityDismissingKeyguard(intent, 0); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java index 5c683f24a8f1..ef501c8efc2a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java @@ -133,7 +133,7 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView { mColorActive = Utils.getColorAttrDefaultColor(context, android.R.attr.colorAccent); mColorDisabled = Utils.getDisabled(context, - Utils.getColorAttrDefaultColor(context, android.R.attr.textColorTertiary)); + Utils.getColorAttrDefaultColor(context, android.R.attr.colorControlActivated)); mColorInactive = Utils.getColorAttrDefaultColor(context, android.R.attr.textColorSecondary); setPadding(0, 0, 0, 0); diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java index 6c4f8083788a..53ff1dfd277b 100644 --- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java +++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java @@ -17,6 +17,9 @@ package com.android.systemui.settings.brightness; import android.content.Context; +import android.graphics.drawable.ClipDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; @@ -27,6 +30,7 @@ import android.widget.SeekBar; import androidx.annotation.Nullable; import com.android.settingslib.RestrictedLockUtils; +import com.android.settingslib.Utils; import com.android.systemui.R; import com.android.systemui.statusbar.policy.BrightnessMirrorController; import com.android.systemui.util.ViewController; @@ -269,14 +273,45 @@ public class BrightnessSlider private BrightnessSlider fromTree(ViewGroup root, boolean useMirror) { BrightnessSliderView v = root.requireViewById(R.id.brightness_slider); + + // TODO(175026098) Workaround. Remove when b/175026098 is fixed + applyTheme(v); + return new BrightnessSlider(root, v, useMirror); } /** Get the layout to inflate based on what slider to use */ - public int getLayout() { + private int getLayout() { return mSettings.useThickSlider() ? R.layout.quick_settings_brightness_dialog_thick : R.layout.quick_settings_brightness_dialog; } + + private LayerDrawable findProgressClippableDrawable(BrightnessSliderView v) { + SeekBar b = v.requireViewById(R.id.slider); + if (b.getProgressDrawable() instanceof LayerDrawable) { + Drawable progress = ((LayerDrawable) b.getProgressDrawable()) + .findDrawableByLayerId(com.android.internal.R.id.progress); + if (progress instanceof ClipDrawable) { + Drawable inner = ((ClipDrawable) progress).getDrawable(); + if (inner instanceof LayerDrawable) { + return (LayerDrawable) inner; + } + } + } + return null; + } + + private void applyTheme(BrightnessSliderView v) { + LayerDrawable layer = findProgressClippableDrawable(v); + if (layer != null) { + layer.findDrawableByLayerId(R.id.slider_foreground).setTintList( + Utils.getColorAttr(v.getContext(), + com.android.internal.R.attr.colorControlActivated)); + layer.findDrawableByLayerId(R.id.slider_icon).setTintList( + Utils.getColorAttr(v.getContext(), + com.android.internal.R.attr.colorBackground)); + } + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java index 4c78e6278be1..149ee8c05348 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java @@ -19,7 +19,6 @@ package com.android.systemui.statusbar.notification.row; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.service.notification.NotificationListenerService.Ranking.RANKING_DEMOTED; import static android.service.notification.NotificationListenerService.Ranking.RANKING_PROMOTED; -import static android.service.notification.NotificationListenerService.Ranking.RANKING_UNCHANGED; import android.annotation.SuppressLint; import android.app.Notification; @@ -43,6 +42,7 @@ import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.Dependency; import com.android.systemui.R; +import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.statusbar.notification.AssistantFeedbackController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -64,6 +64,9 @@ public class FeedbackInfo extends LinearLayout implements NotificationGuts.GutsC private NotificationEntryManager mNotificationEntryManager; private IStatusBarService mStatusBarService; private AssistantFeedbackController mFeedbackController; + private NotificationGutsManager mNotificationGutsManager; + private NotificationMenuRowPlugin mMenuRowPlugin; + private ExpandableNotificationRow mExpandableNotificationRow; public FeedbackInfo(Context context, AttributeSet attrs) { super(context, attrs); @@ -73,19 +76,21 @@ public class FeedbackInfo extends LinearLayout implements NotificationGuts.GutsC final PackageManager pm, final StatusBarNotification sbn, final NotificationEntry entry, + final ExpandableNotificationRow row, final AssistantFeedbackController controller) { mPkg = sbn.getPackageName(); mPm = pm; mEntry = entry; + mExpandableNotificationRow = row; mRanking = entry.getRanking(); mFeedbackController = controller; mAppName = mPkg; mNotificationEntryManager = Dependency.get(NotificationEntryManager.class); mStatusBarService = Dependency.get(IStatusBarService.class); + mNotificationGutsManager = Dependency.get(NotificationGutsManager.class); bindHeader(); bindPrompt(); - bindButton(); } private void bindHeader() { @@ -161,27 +166,24 @@ public class FeedbackInfo extends LinearLayout implements NotificationGuts.GutsC return sb.toString(); } - private void bindButton() { - TextView ok = findViewById(R.id.ok); - ok.setOnClickListener(this::closeControls); - } - private void positiveFeedback(View v) { + mGutsContainer.closeControls(v, false); handleFeedback(true); } private void negativeFeedback(View v) { + mMenuRowPlugin = mExpandableNotificationRow.getProvider(); + NotificationMenuRowPlugin.MenuItem menuItem = null; + if (mMenuRowPlugin != null) { + menuItem = mMenuRowPlugin.getLongpressMenuItem(mContext); + } + + mGutsContainer.closeControls(v, false); + mNotificationGutsManager.openGuts(mExpandableNotificationRow, 0, 0, menuItem); handleFeedback(false); } private void handleFeedback(boolean positive) { - TextView prompt = findViewById(R.id.prompt); - prompt.setText(mContext.getString(R.string.feedback_response)); - TextView yes = findViewById(R.id.yes); - yes.setVisibility(View.GONE); - TextView no = findViewById(R.id.no); - no.setVisibility(View.GONE); - Bundle feedback = new Bundle(); feedback.putBoolean(FEEDBACK_KEY, positive); sendFeedbackToAssistant(feedback); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java index d2cfb2908e9c..c4f009815ba6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java @@ -324,7 +324,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx userHandle.getIdentifier()); if (mAssistantFeedbackController.showFeedbackIndicator(row.getEntry())) { - feedbackInfo.bindGuts(pmUser, sbn, row.getEntry(), mAssistantFeedbackController); + feedbackInfo.bindGuts(pmUser, sbn, row.getEntry(), row, mAssistantFeedbackController); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java index 4c9c2f95b35c..414d62092ab2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java @@ -47,6 +47,10 @@ public class NotificationCustomViewWrapper extends NotificationViewWrapper { public void onContentUpdated(ExpandableNotificationRow row) { super.onContentUpdated(row); + // Custom views will most likely use just white or black as their text color. + // We need to scan through and replace these colors by Material NEXT colors. + ensureThemeOnChildren(); + // Let's invert the notification colors when we're in night mode and // the notification background isn't colorized. if (needsInversion(mBackgroundColor, mView)) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java index 49a8d56e1e65..79648457c521 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java @@ -43,6 +43,11 @@ public class NotificationDecoratedCustomViewWrapper extends NotificationTemplate if (childIndex != null && childIndex != -1) { mWrappedView = container.getChildAt(childIndex); } + + // Custom views will most likely use just white or black as their text color. + // We need to scan through and replace these colors by Material NEXT colors. + ensureThemeOnChildren(); + if (needsInversion(resolveBackgroundColor(), mWrappedView)) { invertViewLuminosity(mWrappedView); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java index 416c5af93400..2d706a48e90d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java @@ -29,11 +29,13 @@ import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Build; +import android.view.ContextThemeWrapper; import android.view.NotificationHeaderView; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.ColorUtils; import com.android.internal.util.ContrastColorUtil; @@ -55,6 +57,9 @@ public abstract class NotificationViewWrapper implements TransformableView { private final Rect mTmpRect = new Rect(); protected int mBackgroundColor = 0; + private int mLightTextColor; + private int mDarkTextColor; + private int mDefaultTextColor; public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) { if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) { @@ -110,6 +115,15 @@ public abstract class NotificationViewWrapper implements TransformableView { mBackgroundColor = backgroundColor; mView.setBackground(new ColorDrawable(Color.TRANSPARENT)); } + mLightTextColor = mView.getContext().getColor( + com.android.internal.R.color.notification_primary_text_color_light); + mDarkTextColor = mView.getContext().getColor( + R.color.notification_primary_text_color_dark); + + Context themedContext = new ContextThemeWrapper(mView.getContext(), + R.style.Theme_DeviceDefault_DayNight); + mDefaultTextColor = Utils.getColorAttr(themedContext, R.attr.textColorPrimary) + .getDefaultColor(); } protected boolean needsInversion(int defaultBackgroundColor, View view) { @@ -187,6 +201,42 @@ public abstract class NotificationViewWrapper implements TransformableView { return false; } + protected void ensureThemeOnChildren() { + if (mView == null) { + return; + } + + // Notifications with custom backgrounds should not be adjusted + if (mBackgroundColor != Color.TRANSPARENT + || getBackgroundColor(mView) != Color.TRANSPARENT) { + return; + } + + // Now let's check if there's unprotected text somewhere, and apply the theme if we find it. + if (!(mView instanceof ViewGroup)) { + return; + } + processChildrenTextColor((ViewGroup) mView); + } + + private void processChildrenTextColor(ViewGroup viewGroup) { + if (viewGroup == null) { + return; + } + + for (int i = 0; i < viewGroup.getChildCount(); i++) { + View child = viewGroup.getChildAt(i); + if (child instanceof TextView) { + int foreground = ((TextView) child).getCurrentTextColor(); + if (foreground == mLightTextColor || foreground == mDarkTextColor) { + ((TextView) child).setTextColor(mDefaultTextColor); + } + } else if (child instanceof ViewGroup) { + processChildrenTextColor((ViewGroup) child); + } + } + } + protected int getBackgroundColor(View view) { if (view == null) { return Color.TRANSPARENT; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java index a5667bb513e0..e1eaf3c17357 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java @@ -390,17 +390,17 @@ public final class DozeServiceHost implements DozeHost { } @Override - public void setDozeScreenBrightness(int value) { - mNotificationShadeWindowController.setDozeScreenBrightness(value); + public void setDozeScreenBrightness(int brightness) { + mDozeLog.traceDozeScreenBrightness(brightness); + mNotificationShadeWindowController.setDozeScreenBrightness(brightness); } @Override public void setAodDimmingScrim(float scrimOpacity) { + mDozeLog.traceSetAodDimmingScrim(scrimOpacity); mScrimController.setAodFrontScrimAlpha(scrimOpacity); } - - @Override public void prepareForGentleSleep(Runnable onDisplayOffCallback) { if (mPendingScreenOffCallback != null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java index 1a2d1cfdcfb4..b9e8d74d9b85 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java @@ -116,6 +116,11 @@ public class KeyguardClockPositionAlgorithm { */ private float mDarkAmount; + /** + * How visible the quick settings panel is. + */ + private float mQsExpansion; + private float mEmptyDragAmount; /** @@ -159,7 +164,8 @@ public class KeyguardClockPositionAlgorithm { public void setup(int statusBarMinHeight, int maxShadeBottom, int notificationStackHeight, float panelExpansion, int parentHeight, int keyguardStatusHeight, int clockPreferredY, boolean hasCustomClock, boolean hasVisibleNotifs, float dark, float emptyDragAmount, - boolean bypassEnabled, int unlockedStackScrollerPadding, boolean udfpsEnrolled) { + boolean bypassEnabled, int unlockedStackScrollerPadding, boolean udfpsEnrolled, + float qsExpansion) { mMinTopMargin = statusBarMinHeight + (udfpsEnrolled ? mContainerTopPaddingWithoutLockIcon : mContainerTopPaddingWithLockIcon); mMaxShadeBottom = maxShadeBottom; @@ -174,6 +180,7 @@ public class KeyguardClockPositionAlgorithm { mEmptyDragAmount = emptyDragAmount; mBypassEnabled = bypassEnabled; mUnlockedStackScrollerPadding = unlockedStackScrollerPadding; + mQsExpansion = qsExpansion; } public void run(Result result) { @@ -274,6 +281,7 @@ public class KeyguardClockPositionAlgorithm { */ private float getClockAlpha(int y) { float alphaKeyguard = Math.max(0, y / Math.max(1f, getClockY(1f))); + alphaKeyguard *= (1f - mQsExpansion); alphaKeyguard = Interpolators.ACCELERATE.getInterpolation(alphaKeyguard); return MathUtils.lerp(alphaKeyguard, 1f, mDarkAmount); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 84eacdc41841..01a729235eda 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -292,6 +292,7 @@ public class NotificationPanelViewController extends PanelViewController { private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory; private final QSDetailDisplayer mQSDetailDisplayer; + private final ScrimController mScrimController; // Maximum # notifications to show on Keyguard; extras will be collapsed in an overflow card. // If there are exactly 1 + mMaxKeyguardNotifications, then still shows all notifications private final int mMaxKeyguardNotifications; @@ -549,6 +550,7 @@ public class NotificationPanelViewController extends PanelViewController { NotificationIconAreaController notificationIconAreaController, AuthController authController, QSDetailDisplayer qsDetailDisplayer, + ScrimController scrimController, MediaDataManager mediaDataManager) { super(view, falsingManager, dozeLog, keyguardStateController, (SysuiStatusBarStateController) statusBarStateController, vibratorHelper, @@ -579,6 +581,7 @@ public class NotificationPanelViewController extends PanelViewController { mPulseExpansionHandler = pulseExpansionHandler; mDozeParameters = dozeParameters; mBiometricUnlockController = biometricUnlockController; + mScrimController = scrimController; mMediaDataManager = mediaDataManager; pulseExpansionHandler.setPulseExpandAbortListener(() -> { if (mQs != null) { @@ -909,7 +912,7 @@ public class NotificationPanelViewController extends PanelViewController { clockPreferredY, hasCustomClock(), hasVisibleNotifications, mInterpolatedDarkAmount, mEmptyDragAmount, bypassEnabled, getUnlockedStackScrollerPadding(), - mUpdateMonitor.isUdfpsEnrolled()); + mUpdateMonitor.isUdfpsEnrolled(), getQsExpansionFraction()); mClockPositionAlgorithm.run(mClockPositionResult); mKeyguardStatusViewController.updatePosition( mClockPositionResult.clockX, mClockPositionResult.clockY, @@ -1756,6 +1759,7 @@ public class NotificationPanelViewController extends PanelViewController { updateHeaderKeyguardAlpha(); if (mBarState == StatusBarState.SHADE_LOCKED || mBarState == KEYGUARD) { updateKeyguardBottomAreaAlpha(); + positionClockAndNotifications(); updateBigClockAlpha(); } @@ -1782,6 +1786,7 @@ public class NotificationPanelViewController extends PanelViewController { float qsExpansionFraction = getQsExpansionFraction(); mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation()); mMediaHierarchyManager.setQsExpansion(qsExpansionFraction); + mScrimController.setQsExpansion(qsExpansionFraction); mNotificationStackScrollLayoutController.setQsExpansionFraction(qsExpansionFraction); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java index ba4fbb871b97..2ac9f301a89a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java @@ -238,7 +238,7 @@ public class NotificationShadeWindowViewController { if (mTouchCancelled || mExpandAnimationRunning || mExpandAnimationPending) { return false; } - mFalsingCollector.onTouchEvent(ev, mView.getWidth(), mView.getHeight()); + mFalsingCollector.onTouchEvent(ev); mGestureDetector.onTouchEvent(ev); if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == View.VISIBLE) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 9e7efc12f4f7..f8e361fb5b6c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -125,11 +125,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump */ public static final float BUSY_SCRIM_ALPHA = 1f; - /** - * Same as above, but when blur is supported. - */ - public static final float BLUR_SCRIM_ALPHA = 0.80f; - static final int TAG_KEY_ANIM = R.id.scrim; private static final int TAG_START_ALPHA = R.id.scrim_alpha_start; private static final int TAG_END_ALPHA = R.id.scrim_alpha_end; @@ -161,6 +156,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump // Assuming the shade is expanded during initialization private float mExpansionFraction = 1f; + private float mQsExpansion; private boolean mDarkenWhileDragging; private boolean mExpansionAffectsAlpha = true; @@ -206,8 +202,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump BlurUtils blurUtils, ConfigurationController configurationController) { mScrimStateListener = lightBarController::setScrimState; - mDefaultScrimAlpha = blurUtils.supportsBlursOnWindows() - ? BLUR_SCRIM_ALPHA : BUSY_SCRIM_ALPHA; + mDefaultScrimAlpha = BUSY_SCRIM_ALPHA; mBlurUtils = blurUtils; mKeyguardStateController = keyguardStateController; @@ -464,6 +459,31 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump boolean relevantState = (mState == ScrimState.UNLOCKED || mState == ScrimState.KEYGUARD + || mState == ScrimState.SHADE_LOCKED + || mState == ScrimState.PULSING + || mState == ScrimState.BUBBLE_EXPANDED); + if (!(relevantState && mExpansionAffectsAlpha)) { + return; + } + applyAndDispatchExpansion(); + } + } + + /** + * Current state of the QuickSettings expansion when pulling it from the top. + * + * @param fraction From 0 to 1 where 0 means collapsed and 1 expanded. + */ + public void setQsExpansion(float fraction) { + if (isNaN(fraction)) { + return; + } + if (mQsExpansion != fraction) { + mQsExpansion = fraction; + Log.d(TAG, "set qs fraction"); + + boolean relevantState = (mState == ScrimState.SHADE_LOCKED + || mState == ScrimState.KEYGUARD || mState == ScrimState.PULSING || mState == ScrimState.BUBBLE_EXPANDED); if (!(relevantState && mExpansionAffectsAlpha)) { @@ -506,7 +526,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump behindFraction = (float) Math.pow(behindFraction, 0.8f); mBehindAlpha = behindFraction * mDefaultScrimAlpha; mInFrontAlpha = 0; - } else if (mState == ScrimState.KEYGUARD || mState == ScrimState.PULSING) { + } else if (mState == ScrimState.KEYGUARD || mState == ScrimState.SHADE_LOCKED + || mState == ScrimState.PULSING) { // Either darken of make the scrim transparent when you // pull down the shade float interpolatedFract = getInterpolatedFraction(); @@ -522,6 +543,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump } mBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(), mState.getBehindTint(), interpolatedFract); + if (mQsExpansion > 0) { + mBehindAlpha = MathUtils.lerp(mBehindAlpha, mDefaultScrimAlpha, mQsExpansion); + mBehindTint = ColorUtils.blendARGB(mBehindTint, + ScrimState.SHADE_LOCKED.getBehindTint(), mQsExpansion); + } } if (isNaN(mBehindAlpha) || isNaN(mInFrontAlpha)) { throw new IllegalStateException("Scrim opacity is NaN for state: " + mState diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java index fc91c16f1a48..994da79204be 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java @@ -112,6 +112,15 @@ public enum ScrimState { } }, + SHADE_LOCKED { + @Override + public void prepare(ScrimState previousState) { + mBehindAlpha = mDefaultScrimAlpha; + mBubbleAlpha = 0f; + mFrontAlpha = 0f; + } + }, + /** * Changing screen brightness from quick settings. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 981f9a662deb..9ebde53bb38b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -4099,6 +4099,8 @@ public class StatusBar extends SystemUI implements DemoMode, mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback); } else if (mBrightnessMirrorVisible) { mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR); + } else if (mState == StatusBarState.SHADE_LOCKED) { + mScrimController.transitionTo(ScrimState.SHADE_LOCKED); } else if (mDozeServiceHost.isPulsing()) { mScrimController.transitionTo(ScrimState.PULSING, mDozeScrimController.getScrimCallback()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java index d8710bf85a6c..8c67072a15d9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java @@ -37,7 +37,6 @@ import com.android.settingslib.fuelgauge.BatterySaverUtils; import com.android.settingslib.fuelgauge.Estimate; import com.android.settingslib.utils.PowerUtil; import com.android.systemui.broadcast.BroadcastDispatcher; -import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.demomode.DemoMode; @@ -49,13 +48,10 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; -import javax.inject.Inject; - /** * Default implementation of a {@link BatteryController}. This controller monitors for battery * level change events that are broadcasted by the system. */ -@SysUISingleton public class BatteryControllerImpl extends BroadcastReceiver implements BatteryController { private static final String TAG = "BatteryController"; @@ -89,7 +85,6 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC private boolean mFetchingEstimate = false; @VisibleForTesting - @Inject public BatteryControllerImpl( Context context, EnhancedEstimates enhancedEstimates, @@ -155,8 +150,11 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC mChangeCallbacks.add(cb); } if (!mHasReceivedBattery) return; + + // Make sure new callbacks get the correct initial state cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging); cb.onPowerSaveChanged(mPowerSave); + cb.onBatteryUnknownStateChanged(mStateUnknown); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt index 92e5b78f776a..27e40e06fcf0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt @@ -56,7 +56,8 @@ class BatteryStateNotifier @Inject constructor( val intent = Intent(Intent.ACTION_VIEW, Uri.parse(context.getString(R.string.config_batteryStateUnknownUrl))) - val pi = PendingIntent.getActivity(context, 0, intent, 0) + val pi = PendingIntent.getActivity(context, 0, intent, + PendingIntent.FLAG_IMMUTABLE) val builder = Notification.Builder(context, channel.id) .setAutoCancel(false) @@ -87,4 +88,4 @@ class BatteryStateNotifier @Inject constructor( private const val TAG = "BatteryStateNotifier" private const val ID = 666 -private const val DELAY_MILLIS: Long = 4 * 60 * 60 * 1000
\ No newline at end of file +private const val DELAY_MILLIS: Long = 4 * 60 * 60 * 1000 diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index 49be648755c3..dd9165d0697b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -15,6 +15,10 @@ */ package com.android.systemui.statusbar.policy; +import static com.android.settingslib.mobile.MobileMappings.getIconKey; +import static com.android.settingslib.mobile.MobileMappings.toDisplayIconKey; +import static com.android.settingslib.mobile.MobileMappings.toIconKey; + import android.content.Context; import android.content.Intent; import android.database.ContentObserver; @@ -22,10 +26,8 @@ import android.net.NetworkCapabilities; import android.os.Handler; import android.os.Looper; import android.provider.Settings.Global; -import android.telephony.Annotation; import android.telephony.CellSignalStrength; import android.telephony.CellSignalStrengthCdma; -import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.SubscriptionInfo; @@ -39,12 +41,13 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.settingslib.Utils; import com.android.settingslib.graph.SignalDrawable; +import com.android.settingslib.mobile.MobileStatusTracker; +import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults; import com.android.settingslib.net.SignalStrengthUtil; import com.android.systemui.R; import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config; -import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults; import java.io.PrintWriter; import java.util.BitSet; @@ -52,8 +55,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.concurrent.Executor; - public class MobileSignalController extends SignalController< MobileSignalController.MobileState, MobileSignalController.MobileIconGroup> { @@ -62,14 +63,10 @@ public class MobileSignalController extends SignalController< private final String mNetworkNameDefault; private final String mNetworkNameSeparator; private final ContentObserver mObserver; - @VisibleForTesting - final PhoneStateListener mPhoneStateListener; // Save entire info for logging, we only use the id. final SubscriptionInfo mSubscriptionInfo; - // @VisibleForDemoMode final Map<String, MobileIconGroup> mNetworkToIconLookup; - // Since some pieces of the phone state are interdependent we store it locally, // this could potentially become part of MobileState for simplification/complication // of code. @@ -83,6 +80,9 @@ public class MobileSignalController extends SignalController< private Config mConfig; @VisibleForTesting boolean mInflateSignalStrengths = false; + private MobileStatusTracker.Callback mCallback; + @VisibleForTesting + MobileStatusTracker mMobileStatusTracker; // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't // need listener lists anymore. @@ -98,28 +98,42 @@ public class MobileSignalController extends SignalController< mPhone = phone; mDefaults = defaults; mSubscriptionInfo = info; - mPhoneStateListener = new MobilePhoneStateListener((new Handler(receiverLooper))::post); mNetworkNameSeparator = getTextIfExists(R.string.status_bar_network_name_separator) .toString(); mNetworkNameDefault = getTextIfExists( com.android.internal.R.string.lockscreen_carrier_default).toString(); - mapIconSets(); - String networkName = info.getCarrierName() != null ? info.getCarrierName().toString() : mNetworkNameDefault; mLastState.networkName = mCurrentState.networkName = networkName; mLastState.networkNameData = mCurrentState.networkNameData = networkName; mLastState.enabled = mCurrentState.enabled = hasMobileData; mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons; - // Get initial data sim state. - updateDataSim(); mObserver = new ContentObserver(new Handler(receiverLooper)) { @Override public void onChange(boolean selfChange) { updateTelephony(); } }; + mCallback = new MobileStatusTracker.Callback() { + @Override + public void onMobileStatusChanged(boolean updateTelephony, + MobileStatusTracker.MobileStatus mobileStatus) { + if (Log.isLoggable(mTag, Log.DEBUG)) { + Log.d(mTag, "onMobileStatusChanged=" + + " updateTelephony=" + updateTelephony + + " mobileStatus=" + mobileStatus.toString()); + } + updateMobileStatus(mobileStatus); + if (updateTelephony) { + updateTelephony(); + } else { + notifyListenersIfNecessary(); + } + } + }; + mMobileStatusTracker = new MobileStatusTracker(mPhone, receiverLooper, + info, mDefaults, mCallback); } public void setConfiguration(Config config) { @@ -157,15 +171,7 @@ public class MobileSignalController extends SignalController< * Start listening for phone state changes. */ public void registerListener() { - mPhone.listen(mPhoneStateListener, - PhoneStateListener.LISTEN_SERVICE_STATE - | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS - | PhoneStateListener.LISTEN_CALL_STATE - | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE - | PhoneStateListener.LISTEN_DATA_ACTIVITY - | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE - | PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE - | PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED); + mMobileStatusTracker.setListening(true); mContext.getContentResolver().registerContentObserver(Global.getUriFor(Global.MOBILE_DATA), true, mObserver); mContext.getContentResolver().registerContentObserver(Global.getUriFor( @@ -177,7 +183,7 @@ public class MobileSignalController extends SignalController< * Stop listening for phone state changes. */ public void unregisterListener() { - mPhone.listen(mPhoneStateListener, 0); + mMobileStatusTracker.setListening(false); mContext.getContentResolver().unregisterContentObserver(mObserver); } @@ -288,34 +294,6 @@ public class MobileSignalController extends SignalController< TelephonyIcons.NR_5G); } - private String getIconKey() { - if (mTelephonyDisplayInfo.getOverrideNetworkType() - == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) { - return toIconKey(mTelephonyDisplayInfo.getNetworkType()); - } else { - return toDisplayIconKey(mTelephonyDisplayInfo.getOverrideNetworkType()); - } - } - - private String toIconKey(@Annotation.NetworkType int networkType) { - return Integer.toString(networkType); - } - - private String toDisplayIconKey(@Annotation.OverrideNetworkType int displayNetworkType) { - switch (displayNetworkType) { - case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA: - return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA"; - case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO: - return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA_Plus"; - case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA: - return toIconKey(TelephonyManager.NETWORK_TYPE_NR); - case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE: - return toIconKey(TelephonyManager.NETWORK_TYPE_NR) + "_Plus"; - default: - return "unsupported"; - } - } - private void updateInflateSignalStrength() { mInflateSignalStrengths = SignalStrengthUtil.shouldInflateSignalStrength(mContext, mSubscriptionInfo.getSubscriptionId()); @@ -521,13 +499,24 @@ public class MobileSignalController extends SignalController< return CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; } + private void updateMobileStatus(MobileStatusTracker.MobileStatus mobileStatus) { + mCurrentState.activityIn = mobileStatus.activityIn; + mCurrentState.activityOut = mobileStatus.activityOut; + mCurrentState.dataSim = mobileStatus.dataSim; + mCurrentState.carrierNetworkChangeMode = mobileStatus.carrierNetworkChangeMode; + mDataState = mobileStatus.dataState; + mServiceState = mobileStatus.serviceState; + mSignalStrength = mobileStatus.signalStrength; + mTelephonyDisplayInfo = mobileStatus.telephonyDisplayInfo; + } + /** * Updates the current state based on mServiceState, mSignalStrength, mDataState, * mTelephonyDisplayInfo, and mSimState. It should be called any time one of these is updated. * This will call listeners if necessary. */ private final void updateTelephony() { - if (DEBUG) { + if (Log.isLoggable(mTag, Log.DEBUG)) { Log.d(mTag, "updateTelephonySignalStrength: hasService=" + Utils.isInService(mServiceState) + " ss=" + mSignalStrength + " displayInfo=" + mTelephonyDisplayInfo); @@ -542,7 +531,7 @@ public class MobileSignalController extends SignalController< } } - String iconKey = getIconKey(); + String iconKey = getIconKey(mTelephonyDisplayInfo); if (mNetworkToIconLookup.get(iconKey) != null) { mCurrentState.iconGroup = mNetworkToIconLookup.get(iconKey); } else { @@ -622,75 +611,6 @@ public class MobileSignalController extends SignalController< pw.println(" isDataDisabled=" + isDataDisabled() + ","); } - class MobilePhoneStateListener extends PhoneStateListener { - public MobilePhoneStateListener(Executor executor) { - super(executor); - } - - @Override - public void onSignalStrengthsChanged(SignalStrength signalStrength) { - if (DEBUG) { - Log.d(mTag, "onSignalStrengthsChanged signalStrength=" + signalStrength + - ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel()))); - } - mSignalStrength = signalStrength; - updateTelephony(); - } - - @Override - public void onServiceStateChanged(ServiceState state) { - if (DEBUG) { - Log.d(mTag, "onServiceStateChanged voiceState=" + state.getState() - + " dataState=" + state.getDataRegistrationState()); - } - mServiceState = state; - updateTelephony(); - } - - @Override - public void onDataConnectionStateChanged(int state, int networkType) { - if (DEBUG) { - Log.d(mTag, "onDataConnectionStateChanged: state=" + state - + " type=" + networkType); - } - mDataState = state; - updateTelephony(); - } - - @Override - public void onDataActivity(int direction) { - if (DEBUG) { - Log.d(mTag, "onDataActivity: direction=" + direction); - } - setActivity(direction); - } - - @Override - public void onCarrierNetworkChange(boolean active) { - if (DEBUG) { - Log.d(mTag, "onCarrierNetworkChange: active=" + active); - } - mCurrentState.carrierNetworkChangeMode = active; - updateTelephony(); - } - - @Override - public void onActiveDataSubscriptionIdChanged(int subId) { - if (DEBUG) Log.d(mTag, "onActiveDataSubscriptionIdChanged: subId=" + subId); - updateDataSim(); - updateTelephony(); - } - - @Override - public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) { - if (DEBUG) { - Log.d(mTag, "onDisplayInfoChanged: telephonyDisplayInfo=" + telephonyDisplayInfo); - } - mTelephonyDisplayInfo = telephonyDisplayInfo; - updateTelephony(); - } - } - static class MobileIconGroup extends SignalController.IconGroup { final int mDataContentDescription; // mContentDescriptionDataType final int mDataType; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index 62b922e23532..a3abb31a36e4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -59,6 +59,7 @@ import androidx.annotation.NonNull; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults; import com.android.settingslib.net.DataUsageController; import com.android.systemui.Dumpable; import com.android.systemui.R; @@ -391,7 +392,6 @@ public class NetworkControllerImpl extends BroadcastReceiver } } }); - updateMobileControllers(); // Initial setup of emergency information. Handled as if we had received a sticky broadcast @@ -1202,20 +1202,6 @@ public class NetworkControllerImpl extends BroadcastReceiver } }; - public static class SubscriptionDefaults { - public int getDefaultVoiceSubId() { - return SubscriptionManager.getDefaultVoiceSubscriptionId(); - } - - public int getDefaultDataSubId() { - return SubscriptionManager.getDefaultDataSubscriptionId(); - } - - public int getActiveDataSubId() { - return SubscriptionManager.getActiveDataSubscriptionId(); - } - } - @VisibleForTesting static class Config { boolean showAtLeast3G = false; diff --git a/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java b/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java new file mode 100644 index 000000000000..79a197d9d409 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.util; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.res.ColorStateList; +import android.content.res.Resources; +import android.content.res.Resources.Theme; +import android.content.res.TypedArray; +import android.graphics.drawable.DrawableWrapper; +import android.util.AttributeSet; + +import com.android.systemui.R; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; + +/** + * An extension of {@link DrawableWrapper} that supports alpha and tint XML properties. + * + * {@link DrawableWrapper} supports setting these properties programmatically, but doesn't expose + * corresponding XML properties for some reason. This class allows to set these values in the XML, + * supporting theming. + * + * This class should only be used in XML. + * + * @attr ref android.R.styleable#DrawableWrapper_drawable + * @attr ref R.styleable#AlphaTintDrawableWrapper_tint + * @attr ref R.styleable#AlphaTintDrawableWrapper_alpha + */ +public class AlphaTintDrawableWrapper extends DrawableWrapper { + private ColorStateList mTint; + private int[] mThemeAttrs; + + /** No-arg constructor used by drawable inflation. */ + public AlphaTintDrawableWrapper() { + super(null); + } + + @Override + public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser, + @NonNull AttributeSet attrs, @Nullable Theme theme) + throws XmlPullParserException, IOException { + final TypedArray a = obtainAttributes(r, theme, attrs, + R.styleable.AlphaTintDrawableWrapper); + + super.inflate(r, parser, attrs, theme); + + mThemeAttrs = a.extractThemeAttrs(); + updateStateFromTypedArray(a); + a.recycle(); + + applyTint(); + } + + @Override + public void applyTheme(Theme t) { + super.applyTheme(t); + + if (mThemeAttrs != null) { + final TypedArray a = t.resolveAttributes(mThemeAttrs, + R.styleable.AlphaTintDrawableWrapper); + updateStateFromTypedArray(a); + a.recycle(); + } + + // Ensure tint is reapplied after applying the theme to ensure this drawables' + // tint overrides the underlying drawables' tint. + applyTint(); + } + + @Override + public boolean canApplyTheme() { + return (mThemeAttrs != null && mThemeAttrs.length > 0) || super.canApplyTheme(); + } + + private void updateStateFromTypedArray(@NonNull TypedArray a) { + if (a.hasValue(R.styleable.AlphaTintDrawableWrapper_android_drawable)) { + setDrawable(a.getDrawable(R.styleable.AlphaTintDrawableWrapper_android_drawable)); + } + if (a.hasValue(R.styleable.AlphaTintDrawableWrapper_android_tint)) { + mTint = a.getColorStateList(R.styleable.AlphaTintDrawableWrapper_android_tint); + } + if (a.hasValue(R.styleable.AlphaTintDrawableWrapper_android_alpha)) { + float alpha = a.getFloat(R.styleable.AlphaTintDrawableWrapper_android_alpha, 1); + setAlpha(Math.round(alpha * 255)); + } + } + + private void applyTint() { + if (getDrawable() != null && mTint != null) { + getDrawable().mutate().setTintList(mTint); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java index a879a1ef4b77..2a18f3c550ed 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java @@ -168,6 +168,11 @@ public final class WMShell extends SystemUI mConfigurationController.addCallback(new ConfigurationController.ConfigurationListener() { @Override + public void onConfigChanged(Configuration newConfig) { + pip.onConfigurationChanged(newConfig); + } + + @Override public void onDensityOrFontScaleChanged() { pip.onDensityOrFontScaleChanged(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java index 11150432f757..0451d45a628b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java @@ -143,6 +143,13 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { } @Test + public void showButton_excludeSystemGestureArea() { + mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + + verify(mSpyImageView).setSystemGestureExclusionRects(any(List.class)); + } + + @Test public void showMagnificationButton_setA11yTimeout_postDelayedAnimationWithA11yTimeout() { final int a11yTimeout = 12345; when(mAccessibilityManager.getRecommendedTimeoutMillis(anyInt(), anyInt())).thenReturn( @@ -178,14 +185,17 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { } @Test - public void onConfigurationChanged_buttonIsShowing_setImageResource() { + public void onConfigurationChanged_buttonIsShowing_updateResourcesAndLayout() { mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); resetAndStubMockImageViewAndAnimator(); mMagnificationModeSwitch.onConfigurationChanged(ActivityInfo.CONFIG_DENSITY); + verify(mSpyImageView).setPadding(anyInt(), anyInt(), anyInt(), anyInt()); verify(mSpyImageView).setImageResource( getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN)); + verify(mWindowManager).updateViewLayout(eq(mSpyImageView), any()); + verify(mSpyImageView).setSystemGestureExclusionRects(any(List.class)); } @Test @@ -368,6 +378,11 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { private void resetAndStubMockImageViewAndAnimator() { resetAndStubMockAnimator(); Mockito.reset(mSpyImageView); + doAnswer(invocation -> { + final Runnable runnable = invocation.getArgument(0); + runnable.run(); + return null; + }).when(mSpyImageView).post(any(Runnable.class)); doReturn(mViewPropertyAnimator).when(mSpyImageView).animate(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java index 19f0a15c8936..8c547b127da2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java @@ -20,6 +20,8 @@ import static com.android.systemui.util.mockito.KotlinMockitoHelpersKt.any; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyDouble; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -31,15 +33,19 @@ import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.testing.FakeMetricsLogger; import com.android.systemui.SysuiTestCase; +import com.android.systemui.classifier.FalsingDataProvider.GestureCompleteListener; import com.android.systemui.dock.DockManagerFake; +import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -62,16 +68,25 @@ public class BrightLineClassifierTest extends SysuiTestCase { @Mock private FalsingClassifier mClassifierB; private final List<MotionEvent> mMotionEventList = new ArrayList<>(); + @Mock + private HistoryTracker mHistoryTracker; + private FakeSystemClock mSystemClock = new FakeSystemClock(); + + private final FalsingClassifier.Result mFalsedResult = FalsingClassifier.Result.falsed(1, ""); + private final FalsingClassifier.Result mPassedResult = FalsingClassifier.Result.passed(1); @Before public void setup() { MockitoAnnotations.initMocks(this); + when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(mPassedResult); + when(mClassifierB.classifyGesture(anyDouble(), anyDouble())).thenReturn(mPassedResult); mClassifiers.add(mClassifierA); mClassifiers.add(mClassifierB); when(mFalsingDataProvider.isDirty()).thenReturn(true); when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList); mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider, mDockManager, - mMetricsLogger, mClassifiers, mSingleTapClassfier, mDoubleTapClassifier, false); + mMetricsLogger, mClassifiers, mSingleTapClassfier, mDoubleTapClassifier, + mHistoryTracker, mSystemClock, false); } @Test @@ -98,20 +113,20 @@ public class BrightLineClassifierTest extends SysuiTestCase { @Test public void testIsFalseTouch_ClassifierARejects() { - when(mClassifierA.isFalseTouch()).thenReturn(true); + when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(mFalsedResult); assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isTrue(); } @Test public void testIsFalseTouch_ClassifierBRejects() { - when(mClassifierB.isFalseTouch()).thenReturn(true); + when(mClassifierB.classifyGesture(anyDouble(), anyDouble())).thenReturn(mFalsedResult); assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isTrue(); } @Test public void testIsFalseTouch_FaceAuth() { // Even when the classifiers report a false, we should allow. - when(mClassifierA.isFalseTouch()).thenReturn(true); + when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(mPassedResult); when(mFalsingDataProvider.isJustUnlockedWithFace()).thenReturn(true); assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isFalse(); @@ -120,7 +135,7 @@ public class BrightLineClassifierTest extends SysuiTestCase { @Test public void testIsFalseTouch_Docked() { // Even when the classifiers report a false, we should allow. - when(mClassifierA.isFalseTouch()).thenReturn(true); + when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(mPassedResult); mDockManager.setIsDocked(true); assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isFalse(); @@ -128,37 +143,51 @@ public class BrightLineClassifierTest extends SysuiTestCase { @Test public void testIsFalseTap_BasicCheck() { - when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(false); + when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mFalsedResult); assertThat(mBrightLineFalsingManager.isFalseTap(false)).isTrue(); - when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(true); + when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult); assertThat(mBrightLineFalsingManager.isFalseTap(false)).isFalse(); } @Test public void testIsFalseTap_RobustCheck_NoFaceAuth() { - when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(true); + when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult); mFalsingDataProvider.setJustUnlockedWithFace(false); assertThat(mBrightLineFalsingManager.isFalseTap(true)).isTrue(); } @Test public void testIsFalseTap_RobustCheck_FaceAuth() { - when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(true); + when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult); when(mFalsingDataProvider.isJustUnlockedWithFace()).thenReturn(true); assertThat(mBrightLineFalsingManager.isFalseTap(true)).isFalse(); } @Test public void testIsFalseDoubleTap() { - when(mDoubleTapClassifier.isFalseTouch()).thenReturn(false); + when(mDoubleTapClassifier.classifyGesture()).thenReturn(mPassedResult); assertThat(mBrightLineFalsingManager.isFalseDoubleTap()).isFalse(); - when(mDoubleTapClassifier.isFalseTouch()).thenReturn(true); + when(mDoubleTapClassifier.classifyGesture()).thenReturn(mFalsedResult); assertThat(mBrightLineFalsingManager.isFalseDoubleTap()).isTrue(); } + + @Test + public void testHistory() { + ArgumentCaptor<GestureCompleteListener> gestureCompleteListenerCaptor = + ArgumentCaptor.forClass(GestureCompleteListener.class); + + verify(mFalsingDataProvider).addGestureCompleteListener( + gestureCompleteListenerCaptor.capture()); + + GestureCompleteListener gestureCompleteListener = gestureCompleteListenerCaptor.getValue(); + gestureCompleteListener.onGestureComplete(); + + verify(mHistoryTracker).addResults(any(Collection.class), eq(mSystemClock.uptimeMillis())); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/DiagonalClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/DiagonalClassifierTest.java index 7659db8cc9ef..dafc87133d39 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/DiagonalClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/DiagonalClassifierTest.java @@ -69,93 +69,93 @@ public class DiagonalClassifierTest extends ClassifierTest { @Test public void testPass_UnknownAngle() { when(mDataProvider.getAngle()).thenReturn(Float.MAX_VALUE); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testPass_VerticalSwipe() { when(mDataProvider.getAngle()).thenReturn(UP_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn(DOWN_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testPass_MostlyVerticalSwipe() { when(mDataProvider.getAngle()).thenReturn(UP_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn(UP_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn(DOWN_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn(DOWN_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS * 2); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testPass_BarelyVerticalSwipe() { when(mDataProvider.getAngle()).thenReturn( UP_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn( UP_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn( DOWN_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn( DOWN_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS * 2); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testPass_HorizontalSwipe() { when(mDataProvider.getAngle()).thenReturn(RIGHT_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn(LEFT_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testPass_MostlyHorizontalSwipe() { when(mDataProvider.getAngle()).thenReturn(RIGHT_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn(RIGHT_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn(LEFT_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn(LEFT_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testPass_BarelyHorizontalSwipe() { when(mDataProvider.getAngle()).thenReturn( RIGHT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn( LEFT_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn( LEFT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn( RIGHT_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS * 2); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -163,12 +163,12 @@ public class DiagonalClassifierTest extends ClassifierTest { when(mDataProvider.getInteractionType()).thenReturn(LEFT_AFFORDANCE); when(mDataProvider.getAngle()).thenReturn( RIGHT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getInteractionType()).thenReturn(RIGHT_AFFORDANCE); when(mDataProvider.getAngle()).thenReturn( LEFT_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); // This classifier may return false for other angles, but these are the only // two that actually matter, as affordances generally only travel in these two directions. @@ -182,37 +182,37 @@ public class DiagonalClassifierTest extends ClassifierTest { when(mDataProvider.isVertical()).thenReturn(false); when(mDataProvider.getAngle()).thenReturn( RIGHT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.getAngle()).thenReturn( UP_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS + FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.getAngle()).thenReturn( LEFT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.getAngle()).thenReturn( DOWN_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS + FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); // Vertical Swipes when(mDataProvider.isVertical()).thenReturn(true); when(mDataProvider.getAngle()).thenReturn( RIGHT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS + FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.getAngle()).thenReturn( UP_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.getAngle()).thenReturn( LEFT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS + FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.getAngle()).thenReturn( DOWN_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java index 013fa369e876..f6c14240c8f4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java @@ -51,32 +51,32 @@ public class DistanceClassifierTest extends ClassifierTest { @Test public void testPass_noPointer() { - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test public void testPass_fling() { mClassifier.onTouchEvent(appendDownEvent(1, 1)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mClassifier.onTouchEvent(appendMoveEvent(1, 40)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mClassifier.onTouchEvent(appendUpEvent(1, 80)); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testFail_flingShort() { mClassifier.onTouchEvent(appendDownEvent(1, 1)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mClassifier.onTouchEvent(appendMoveEvent(1, 2)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mClassifier.onTouchEvent(appendUpEvent(1, 10)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -84,26 +84,26 @@ public class DistanceClassifierTest extends ClassifierTest { // These events, in testing, result in a fling that falls just short of the threshold. mClassifier.onTouchEvent(appendDownEvent(1, 1, 1)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mClassifier.onTouchEvent(appendMoveEvent(1, 15, 2)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mClassifier.onTouchEvent(appendMoveEvent(1, 16, 3)); mClassifier.onTouchEvent(appendMoveEvent(1, 17, 300)); mClassifier.onTouchEvent(appendMoveEvent(1, 18, 301)); mClassifier.onTouchEvent(appendUpEvent(1, 19, 501)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test public void testPass_swipe() { mClassifier.onTouchEvent(appendDownEvent(1, 1)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mClassifier.onTouchEvent(appendMoveEvent(1, mDataProvider.getYdpi() * 3, 3)); mClassifier.onTouchEvent(appendUpEvent(1, mDataProvider.getYdpi() * 3, 300)); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/DoubleTapClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/DoubleTapClassifierTest.java index 4c4108a0cb90..17c2700c5bda 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/DoubleTapClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/DoubleTapClassifierTest.java @@ -55,6 +55,9 @@ public class DoubleTapClassifierTest extends ClassifierTest { private SingleTapClassifier mSingleTapClassifier; private DoubleTapClassifier mClassifier; + private final FalsingClassifier.Result mFalsedResult = FalsingClassifier.Result.falsed(1, ""); + private final FalsingClassifier.Result mPassedResult = FalsingClassifier.Result.passed(1); + @Before public void setup() { super.setup(); @@ -77,17 +80,17 @@ public class DoubleTapClassifierTest extends ClassifierTest { @Test public void testSingleTap() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(true); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP, 1); - boolean result = mClassifier.isFalseTouch(); + boolean result = mClassifier.classifyGesture().isFalse(); assertThat("Single tap recognized as a valid double tap", result, is(true)); } @Test public void testDoubleTap() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(true); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mPassedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); @@ -97,13 +100,13 @@ public class DoubleTapClassifierTest extends ClassifierTest { addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, TOUCH_SLOP, TOUCH_SLOP); addMotionEvent(2, 3, MotionEvent.ACTION_UP, TOUCH_SLOP, TOUCH_SLOP); - boolean result = mClassifier.isFalseTouch(); - assertThat(mClassifier.getReason(), result, is(false)); + FalsingClassifier.Result result = mClassifier.classifyGesture(); + assertThat(result.getReason(), result.isFalse(), is(false)); } @Test public void testBadFirstTap() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(false, true); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mPassedResult, mFalsedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); @@ -113,13 +116,13 @@ public class DoubleTapClassifierTest extends ClassifierTest { addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(2, 3, MotionEvent.ACTION_UP, 1, 1); - boolean result = mClassifier.isFalseTouch(); + boolean result = mClassifier.classifyGesture().isFalse(); assertThat("Bad first touch allowed", result, is(true)); } @Test public void testBadSecondTap() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(true, false); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult, mPassedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); @@ -129,13 +132,13 @@ public class DoubleTapClassifierTest extends ClassifierTest { addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(2, 3, MotionEvent.ACTION_UP, 1, 1); - boolean result = mClassifier.isFalseTouch(); + boolean result = mClassifier.classifyGesture().isFalse(); assertThat("Bad second touch allowed", result, is(true)); } @Test public void testBadTouchSlop() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(true); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); @@ -145,13 +148,13 @@ public class DoubleTapClassifierTest extends ClassifierTest { addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, TOUCH_SLOP + 1, TOUCH_SLOP); addMotionEvent(2, 3, MotionEvent.ACTION_UP, TOUCH_SLOP, TOUCH_SLOP + 1); - boolean result = mClassifier.isFalseTouch(); + boolean result = mClassifier.classifyGesture().isFalse(); assertThat("Sloppy second touch allowed", result, is(true)); } @Test public void testBadTouchSlow() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(true); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); @@ -163,7 +166,7 @@ public class DoubleTapClassifierTest extends ClassifierTest { addMotionEvent(DOUBLE_TAP_TIMEOUT_MS + 1, DOUBLE_TAP_TIMEOUT_MS + 2, MotionEvent.ACTION_UP, 1, 1); - boolean result = mClassifier.isFalseTouch(); + boolean result = mClassifier.classifyGesture().isFalse(); assertThat("Slow second tap allowed", result, is(true)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.java new file mode 100644 index 000000000000..01cce3579b0c --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.classifier; + +import static com.google.common.truth.Truth.assertThat; + +import android.testing.AndroidTestingRunner; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.util.time.FakeSystemClock; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; + +import java.util.Collections; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +public class HistoryTrackerTest extends SysuiTestCase { + + private FakeSystemClock mSystemClock = new FakeSystemClock(); + + private HistoryTracker mHistoryTracker; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mHistoryTracker = new HistoryTracker(mSystemClock); + } + + @Test + public void testNoDataNoPenalty() { + assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0); + } + + @Test + public void testOneResultFullConfidence() { + addResult(true, 1); + assertThat(mHistoryTracker.falsePenalty()).isEqualTo(1); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1); + } + + @Test + public void testMultipleResultsSameTimestamp() { + addResult(true, 1); + addResult(false, 1); + + assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0.5); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0.5); + } + + @Test + public void testMultipleConfidences() { + addResult(true, 1); + addResult(true, 0); + + assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0.75); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(.75); + } + + @Test + public void testDecay() { + addResult(true, 1); + + assertThat(mHistoryTracker.falsePenalty()).isEqualTo(1); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1); + + mSystemClock.advanceTime(1000); + + assertThat(mHistoryTracker.falsePenalty()).isWithin(0.01).of(0.1); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1); + } + + @Test + public void testMultipleResultsDifferentTimestamp() { + addResult(true, 1); + mSystemClock.advanceTime(1000); + addResult(false, .5); + + assertThat(mHistoryTracker.falsePenalty()).isWithin(0.01).of(0.17); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0.625); + } + + @Test + public void testCompleteDecay() { + addResult(true, 1); + + assertThat(mHistoryTracker.falsePenalty()).isEqualTo(1); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1); + + mSystemClock.advanceTime(2999); + + assertThat(mHistoryTracker.falsePenalty()).isGreaterThan(0); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1); + + mSystemClock.advanceTime(1); + + assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0); + } + + private void addResult(boolean falsed, double confidence) { + mHistoryTracker.addResults(Collections.singletonList( + falsed + ? FalsingClassifier.Result.falsed(confidence, "test") + : FalsingClassifier.Result.passed(confidence)), + mSystemClock.uptimeMillis()); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/PointerCountClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/PointerCountClassifierTest.java index ee289b5b922d..76802f4de14f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/PointerCountClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/PointerCountClassifierTest.java @@ -50,13 +50,13 @@ public class PointerCountClassifierTest extends ClassifierTest { @Test public void testPass_noPointer() { - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testPass_singlePointer() { mClassifier.onTouchEvent(appendDownEvent(1, 1)); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -72,7 +72,7 @@ public class PointerCountClassifierTest extends ClassifierTest { 0, 0); mClassifier.onTouchEvent(motionEvent); motionEvent.recycle(); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -89,6 +89,6 @@ public class PointerCountClassifierTest extends ClassifierTest { mClassifier.onTouchEvent(motionEvent); motionEvent.recycle(); getDataProvider().setInteractionType(QUICK_SETTINGS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java index 38b025f675ee..ba8ca9abc2d7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java @@ -50,12 +50,16 @@ public class ProximityClassifierTest extends ClassifierTest { private DistanceClassifier mDistanceClassifier; private FalsingClassifier mClassifier; + private final FalsingClassifier.Result mFalsedResult = + FalsingClassifier.Result.falsed(1, "test"); + private final FalsingClassifier.Result mPassedResult = FalsingClassifier.Result.passed(1); + @Before public void setup() { super.setup(); MockitoAnnotations.initMocks(this); when(mDataProvider.getInteractionType()).thenReturn(GENERIC); - when(mDistanceClassifier.isLongSwipe()).thenReturn(false); + when(mDistanceClassifier.isLongSwipe()).thenReturn(mFalsedResult); mClassifier = new ProximityClassifier( mDistanceClassifier, mDataProvider, new DeviceConfigProxyFake()); } @@ -69,7 +73,7 @@ public class ProximityClassifierTest extends ClassifierTest { public void testPass_uncovered() { touchDown(); touchUp(10); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -78,7 +82,7 @@ public class ProximityClassifierTest extends ClassifierTest { mClassifier.onProximityEvent(createSensorEvent(true, 1)); mClassifier.onProximityEvent(createSensorEvent(false, 2)); touchUp(20); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -88,7 +92,7 @@ public class ProximityClassifierTest extends ClassifierTest { mClassifier.onProximityEvent(createSensorEvent(true, 1)); mClassifier.onProximityEvent(createSensorEvent(false, 11)); touchUp(10); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -97,7 +101,7 @@ public class ProximityClassifierTest extends ClassifierTest { mClassifier.onProximityEvent(createSensorEvent(true, 1)); mClassifier.onProximityEvent(createSensorEvent(false, 11)); touchUp(10); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -108,7 +112,7 @@ public class ProximityClassifierTest extends ClassifierTest { mClassifier.onProximityEvent(createSensorEvent(true, 96)); mClassifier.onProximityEvent(createSensorEvent(false, 100)); touchUp(100); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -117,8 +121,8 @@ public class ProximityClassifierTest extends ClassifierTest { mClassifier.onProximityEvent(createSensorEvent(true, 1)); mClassifier.onProximityEvent(createSensorEvent(false, 11)); touchUp(10); - when(mDistanceClassifier.isLongSwipe()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + when(mDistanceClassifier.isLongSwipe()).thenReturn(mPassedResult); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } private void touchDown() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/SingleTapClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/SingleTapClassifierTest.java index 941e12e475f9..62c876f99a15 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/SingleTapClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/SingleTapClassifierTest.java @@ -70,14 +70,14 @@ public class SingleTapClassifierTest extends ClassifierTest { addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP, 1); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); mMotionEvents.clear(); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, -TOUCH_SLOP + 2, 1); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @@ -86,14 +86,14 @@ public class SingleTapClassifierTest extends ClassifierTest { addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, TOUCH_SLOP); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); mMotionEvents.clear(); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, -TOUCH_SLOP + 2); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @@ -102,14 +102,14 @@ public class SingleTapClassifierTest extends ClassifierTest { addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP + 1, 1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mMotionEvents.clear(); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, -TOUCH_SLOP - 1, 1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @@ -118,14 +118,14 @@ public class SingleTapClassifierTest extends ClassifierTest { addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, TOUCH_SLOP + 1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mMotionEvents.clear(); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, -TOUCH_SLOP - 1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -134,7 +134,7 @@ public class SingleTapClassifierTest extends ClassifierTest { addMotionEvent(0, 1, MotionEvent.ACTION_MOVE, 1, TOUCH_SLOP + 1); addMotionEvent(0, 2, MotionEvent.ACTION_UP, 1, 1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -142,12 +142,12 @@ public class SingleTapClassifierTest extends ClassifierTest { addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); - assertThat(mClassifier.isTap(mMotionEvents), is(true)); + assertThat(mClassifier.isTap(mMotionEvents).isFalse(), is(false)); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, TOUCH_SLOP + 1); - assertThat(mClassifier.isTap(mMotionEvents), is(false)); + assertThat(mClassifier.isTap(mMotionEvents).isFalse(), is(true)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java index 6b9bb4fedd16..4a896a8574b9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java @@ -61,10 +61,10 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isUp()).thenReturn(false); when(mDataProvider.isRight()).thenReturn(false); // right should cause no effect. - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -73,11 +73,11 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isVertical()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isVertical()).thenReturn(true); when(mDataProvider.isUp()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -87,10 +87,10 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isUp()).thenReturn(false); when(mDataProvider.isRight()).thenReturn(false); // right should cause no effect. - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -99,11 +99,11 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isVertical()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isVertical()).thenReturn(true); when(mDataProvider.isUp()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -113,10 +113,10 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isUp()).thenReturn(false); when(mDataProvider.isRight()).thenReturn(false); // right should cause no effect. - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -125,11 +125,11 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isVertical()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isVertical()).thenReturn(true); when(mDataProvider.isUp()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -139,19 +139,19 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isUp()).thenReturn(false); // up and right should cause no effect. when(mDataProvider.isRight()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isUp()).thenReturn(true); when(mDataProvider.isRight()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isUp()).thenReturn(false); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isUp()).thenReturn(true); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -161,19 +161,19 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isUp()).thenReturn(false); // up and right should cause no effect. when(mDataProvider.isRight()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isUp()).thenReturn(true); when(mDataProvider.isRight()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isUp()).thenReturn(false); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isUp()).thenReturn(true); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @@ -185,10 +185,10 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isRight()).thenReturn(false); // right should cause no effect. - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -197,15 +197,15 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isVertical()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isVertical()).thenReturn(true); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isVertical()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -216,10 +216,10 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isRight()).thenReturn(false); // right should cause no effect. - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -228,15 +228,15 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isVertical()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isVertical()).thenReturn(true); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isVertical()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -247,10 +247,10 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isVertical()).thenReturn(false); // vertical should cause no effect. - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isVertical()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -259,15 +259,15 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isRight()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isRight()).thenReturn(true); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isRight()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -278,10 +278,10 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isVertical()).thenReturn(false); // vertical should cause no effect. - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isVertical()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -290,14 +290,14 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isUp()).thenReturn(true); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isUp()).thenReturn(false); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isUp()).thenReturn(false); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java index 339dd9e9e6d2..09bee128c673 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java @@ -51,11 +51,11 @@ public class ZigZagClassifierTest extends ClassifierTest { @Test public void testPass_fewTouchesVertical() { - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); appendMoveEvent(0, 0); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); appendMoveEvent(0, 100); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -63,16 +63,16 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(0, 100); appendMoveEvent(0, 200); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testPass_fewTouchesHorizontal() { - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); appendMoveEvent(0, 0); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); appendMoveEvent(100, 0); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -80,7 +80,7 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(100, 0); appendMoveEvent(200, 0); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @@ -89,7 +89,7 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(0, 100); appendMoveEvent(0, 1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -97,7 +97,7 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(100, 0); appendMoveEvent(1, 0); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -105,7 +105,7 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(10, 10); appendMoveEvent(20, 20); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -115,7 +115,7 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(5, 100); appendMoveEvent(-5, 200); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -125,7 +125,7 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(100, 5); appendMoveEvent(200, -5); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -135,7 +135,7 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(6, 10); appendMoveEvent(-6, 20); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -145,7 +145,7 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(10, 5); appendMoveEvent(20, -5); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -153,25 +153,25 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(100, 5); appendMoveEvent(200, 10); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(100, 0); appendMoveEvent(200, 10); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(100, -10); appendMoveEvent(200, 10); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(100, -10); appendMoveEvent(200, 50); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -179,25 +179,25 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(10, 50); appendMoveEvent(8, 100); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(1, 800); appendMoveEvent(2, 900); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-10, 600); appendMoveEvent(30, 700); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(40, 100); appendMoveEvent(0, 101); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -205,25 +205,25 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(-10, 50); appendMoveEvent(-24, 100); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-20, 800); appendMoveEvent(-20, 900); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(30, 600); appendMoveEvent(-10, 700); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-80, 100); appendMoveEvent(-10, 101); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -231,25 +231,25 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(-120, 10); appendMoveEvent(-200, 20); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-20, 8); appendMoveEvent(-40, 2); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-500, -2); appendMoveEvent(-600, 70); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-80, 100); appendMoveEvent(-100, 1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -257,25 +257,25 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(-120, -10); appendMoveEvent(-200, -20); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-20, -8); appendMoveEvent(-40, -2); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-500, 2); appendMoveEvent(-600, -70); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-80, -100); appendMoveEvent(-100, -1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -283,25 +283,25 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(-12, -20); appendMoveEvent(-20, -40); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-20, -130); appendMoveEvent(-40, -260); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(1, -100); appendMoveEvent(-6, -200); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-80, -100); appendMoveEvent(-10, -110); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -309,25 +309,25 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(12, -20); appendMoveEvent(20, -40); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(20, -130); appendMoveEvent(40, -260); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-1, -100); appendMoveEvent(6, -200); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(80, -100); appendMoveEvent(10, -110); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -335,25 +335,25 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(120, -20); appendMoveEvent(200, -40); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(200, -13); appendMoveEvent(400, -30); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(100, 10); appendMoveEvent(600, -20); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(80, -100); appendMoveEvent(100, -1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java index 00598814be5a..2320f4ee2b60 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java @@ -31,7 +31,6 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.app.AlarmManager; import android.database.ContentObserver; import android.hardware.Sensor; import android.hardware.display.AmbientDisplayConfiguration; @@ -65,8 +64,6 @@ import java.util.function.Consumer; public class DozeSensorsTest extends SysuiTestCase { @Mock - private AlarmManager mAlarmManager; - @Mock private AsyncSensorManager mSensorManager; @Mock private DozeParameters mDozeParameters; @@ -79,8 +76,6 @@ public class DozeSensorsTest extends SysuiTestCase { @Mock private Consumer<Boolean> mProxCallback; @Mock - private AlwaysOnDisplayPolicy mAlwaysOnDisplayPolicy; - @Mock private TriggerSensor mTriggerSensor; @Mock private DozeLog mDozeLog; @@ -115,7 +110,7 @@ public class DozeSensorsTest extends SysuiTestCase { @Test public void testSensorDebounce() { - mDozeSensors.setListening(true); + mDozeSensors.setListening(true, true); mWakeLockScreenListener.onSensorChanged(mock(SensorManagerPlugin.SensorEvent.class)); mTestableLooper.processAllMessages(); @@ -133,7 +128,7 @@ public class DozeSensorsTest extends SysuiTestCase { @Test public void testSetListening_firstTrue_registerSettingsObserver() { verify(mSensorManager, never()).registerListener(any(), any(Sensor.class), anyInt()); - mDozeSensors.setListening(true); + mDozeSensors.setListening(true, true); verify(mTriggerSensor).registerSettingsObserver(any(ContentObserver.class)); } @@ -141,8 +136,8 @@ public class DozeSensorsTest extends SysuiTestCase { @Test public void testSetListening_twiceTrue_onlyRegisterSettingsObserverOnce() { verify(mSensorManager, never()).registerListener(any(), any(Sensor.class), anyInt()); - mDozeSensors.setListening(true); - mDozeSensors.setListening(true); + mDozeSensors.setListening(true, true); + mDozeSensors.setListening(true, true); verify(mTriggerSensor, times(1)).registerSettingsObserver(any(ContentObserver.class)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java index 4bbba56395f8..27187a85c040 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java @@ -154,6 +154,7 @@ public class DozeTriggersTest extends SysuiTestCase { clearInvocations(mSensors); mTriggers.transitionTo(DozeMachine.State.DOZE_PULSING, DozeMachine.State.DOZE_PULSE_DONE); + mTriggers.transitionTo(DozeMachine.State.DOZE_PULSE_DONE, DozeMachine.State.DOZE_AOD); waitForSensorManager(); verify(mSensors).requestTriggerSensor(any(), eq(mTapSensor)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java index c897d8a53e20..fd5d99667e0c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java @@ -35,6 +35,7 @@ import android.widget.TextView; import androidx.core.graphics.drawable.IconCompat; import androidx.test.filters.SmallTest; +import com.android.internal.logging.UiEventLogger; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; @@ -61,6 +62,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { private ActivityStarter mStarter = mock(ActivityStarter.class); private NotificationEntryManager mNotificationEntryManager = mock(NotificationEntryManager.class); + private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class); private MediaOutputBaseDialogImpl mMediaOutputBaseDialogImpl; private MediaOutputController mMediaOutputController; @@ -73,7 +75,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { public void setUp() { mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false, mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager); + mNotificationEntryManager, mUiEventLogger); mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext, mMediaOutputController); mMediaOutputBaseDialogImpl.onCreate(new Bundle()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java index 0d352c1b42d9..d1a617bcc0cb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java @@ -42,6 +42,7 @@ import android.text.TextUtils; import androidx.core.graphics.drawable.IconCompat; import androidx.test.filters.SmallTest; +import com.android.internal.logging.UiEventLogger; import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.media.LocalMediaManager; @@ -89,6 +90,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { private ActivityStarter mStarter = mock(ActivityStarter.class); private NotificationEntryManager mNotificationEntryManager = mock(NotificationEntryManager.class); + private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class); private Context mSpyContext; private MediaOutputController mMediaOutputController; @@ -111,7 +113,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME, false, mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager); + mNotificationEntryManager, mUiEventLogger); mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; MediaDescription.Builder builder = new MediaDescription.Builder(); @@ -155,7 +157,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { public void start_withoutPackageName_verifyMediaControllerInit() { mMediaOutputController = new MediaOutputController(mSpyContext, null, false, mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager); + mNotificationEntryManager, mUiEventLogger); mMediaOutputController.start(mCb); @@ -176,7 +178,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { public void stop_withoutPackageName_verifyMediaControllerDeinit() { mMediaOutputController = new MediaOutputController(mSpyContext, null, false, mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager); + mNotificationEntryManager, mUiEventLogger); mMediaOutputController.start(mCb); @@ -200,8 +202,10 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void onSelectedDeviceStateChanged_verifyCallback() { + when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2); mMediaOutputController.start(mCb); reset(mCb); + mMediaOutputController.connectDevice(mMediaDevice1); mMediaOutputController.onSelectedDeviceStateChanged(mMediaDevice1, LocalMediaManager.MediaDeviceState.STATE_CONNECTED); @@ -221,8 +225,10 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void onRequestFailed_verifyCallback() { + when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice1); mMediaOutputController.start(mCb); reset(mCb); + mMediaOutputController.connectDevice(mMediaDevice2); mMediaOutputController.onRequestFailed(0 /* reason */); @@ -268,6 +274,8 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void connectDevice_verifyConnect() { + when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2); + mMediaOutputController.connectDevice(mMediaDevice1); // Wait for background thread execution @@ -441,7 +449,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { public void getNotificationLargeIcon_withoutPackageName_returnsNull() { mMediaOutputController = new MediaOutputController(mSpyContext, null, false, mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager); + mNotificationEntryManager, mUiEventLogger); assertThat(mMediaOutputController.getNotificationIcon()).isNull(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java index c1e7db1f9b5e..86f6bdec43f0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java @@ -19,6 +19,8 @@ package com.android.systemui.media.dialog; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.media.MediaRoute2Info; @@ -29,6 +31,7 @@ import android.view.View; import androidx.test.filters.SmallTest; +import com.android.internal.logging.UiEventLogger; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.media.LocalMediaManager; import com.android.settingslib.media.MediaDevice; @@ -53,26 +56,28 @@ public class MediaOutputDialogTest extends SysuiTestCase { private static final String TEST_PACKAGE = "test_package"; // Mock - private MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class); - private LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class); - private ShadeController mShadeController = mock(ShadeController.class); - private ActivityStarter mStarter = mock(ActivityStarter.class); - private LocalMediaManager mLocalMediaManager = mock(LocalMediaManager.class); - private MediaDevice mMediaDevice = mock(MediaDevice.class); - private NotificationEntryManager mNotificationEntryManager = + private final MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class); + private final LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class); + private final ShadeController mShadeController = mock(ShadeController.class); + private final ActivityStarter mStarter = mock(ActivityStarter.class); + private final LocalMediaManager mLocalMediaManager = mock(LocalMediaManager.class); + private final MediaDevice mMediaDevice = mock(MediaDevice.class); + private final NotificationEntryManager mNotificationEntryManager = mock(NotificationEntryManager.class); + private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class); private MediaOutputDialog mMediaOutputDialog; private MediaOutputController mMediaOutputController; - private List<String> mFeatures = new ArrayList<>(); + private final List<String> mFeatures = new ArrayList<>(); @Before public void setUp() { mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false, mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager); + mNotificationEntryManager, mUiEventLogger); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; - mMediaOutputDialog = new MediaOutputDialog(mContext, false, mMediaOutputController); + mMediaOutputDialog = new MediaOutputDialog(mContext, false, + mMediaOutputController, mUiEventLogger); when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice); when(mMediaDevice.getFeatures()).thenReturn(mFeatures); @@ -112,4 +117,16 @@ public class MediaOutputDialogTest extends SysuiTestCase { assertThat(mMediaOutputDialog.getStopButtonVisibility()).isEqualTo(View.GONE); } + @Test + // Check the visibility metric logging by creating a new MediaOutput dialog, + // and verify if the calling times increases. + public void onCreate_ShouldLogVisibility() { + MediaOutputDialog testDialog = new MediaOutputDialog(mContext, false, + mMediaOutputController, mUiEventLogger); + + testDialog.dismissDialog(); + + verify(mUiEventLogger, times(2)) + .log(MediaOutputDialog.MediaOutputEvent.MEDIA_OUTPUT_DIALOG_SHOW); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java index 581335027671..c296ff5cf19a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java @@ -28,6 +28,7 @@ import android.view.View; import androidx.test.filters.SmallTest; +import com.android.internal.logging.UiEventLogger; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.media.LocalMediaManager; import com.android.settingslib.media.MediaDevice; @@ -62,6 +63,7 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase { private MediaDevice mMediaDevice1 = mock(MediaDevice.class); private NotificationEntryManager mNotificationEntryManager = mock(NotificationEntryManager.class); + private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class); private MediaOutputGroupDialog mMediaOutputGroupDialog; private MediaOutputController mMediaOutputController; @@ -71,7 +73,7 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase { public void setUp() { mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false, mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager); + mNotificationEntryManager, mUiEventLogger); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false, mMediaOutputController); diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java index 477fe6316399..019424cd48f0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java @@ -29,12 +29,20 @@ import static org.mockito.Mockito.when; import static java.util.Objects.requireNonNull; +import android.app.INotificationManager; import android.app.NotificationChannel; -import android.content.Context; +import android.appwidget.AppWidgetManager; +import android.content.SharedPreferences; +import android.content.pm.ParceledListSlice; +import android.content.pm.ShortcutInfo; import android.os.RemoteException; import android.os.UserHandle; +import android.provider.Settings; +import android.service.notification.ConversationChannelWrapper; import android.testing.AndroidTestingRunner; +import android.widget.RemoteViews; +import androidx.preference.PreferenceManager; import androidx.test.filters.SmallTest; import com.android.internal.appwidget.IAppWidgetService; @@ -54,6 +62,9 @@ import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.ArrayList; +import java.util.List; + @SmallTest @RunWith(AndroidTestingRunner.class) public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { @@ -65,14 +76,23 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { private static final String TEST_CHANNEL_NAME = "channel_name"; private static final String TEST_PARENT_CHANNEL_ID = "parent_channel_id"; private static final String TEST_CONVERSATION_ID = "conversation_id"; + private static final int WIDGET_ID_WITH_SHORTCUT = 1; + private static final int WIDGET_ID_WITHOUT_SHORTCUT = 2; + private static final String SHORTCUT_ID = "101"; private PeopleSpaceWidgetManager mManager; - @Mock private NotificationListener mListenerService; - @Mock private IAppWidgetService mIAppWidgetService; - @Mock private Context mContext; + @Mock + private NotificationListener mListenerService; + @Mock + private IAppWidgetService mIAppWidgetService; + @Mock + private AppWidgetManager mAppWidgetManager; + @Mock + private INotificationManager mINotificationManager; - @Captor private ArgumentCaptor<NotificationHandler> mListenerCaptor; + @Captor + private ArgumentCaptor<NotificationHandler> mListenerCaptor; private final NoManSimulator mNoMan = new NoManSimulator(); private final FakeSystemClock mClock = new FakeSystemClock(); @@ -80,18 +100,18 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { @Before public void setUp() { MockitoAnnotations.initMocks(this); - mManager = new PeopleSpaceWidgetManager(mContext); - mManager.setAppWidgetManager(mIAppWidgetService); + mManager.setAppWidgetManager(mIAppWidgetService, mAppWidgetManager, mINotificationManager); mManager.attach(mListenerService); verify(mListenerService).addNotificationHandler(mListenerCaptor.capture()); NotificationHandler serviceListener = requireNonNull(mListenerCaptor.getValue()); mNoMan.addListener(serviceListener); + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 2); } - @Test public void testDoNotNotifyAppWidgetIfNoWidgets() throws RemoteException { int[] widgetIdsArray = {}; @@ -105,7 +125,24 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { verify(mIAppWidgetService, times(1)).getAppWidgetIds(any()); verify(mIAppWidgetService, never()).notifyAppWidgetViewDataChanged(any(), any(), anyInt()); + } + + @Test + public void testDoNotNotifySingleConversationAppWidgetIfNoWidgets() throws RemoteException { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0); + int[] widgetIdsArray = {}; + when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray); + + NotifEvent notif1 = mNoMan.postNotif( + new NotificationEntryBuilder() + .setId(0) + .setPkg(TEST_PACKAGE_A)); + mClock.advanceTime(MIN_LINGER_DURATION); + verify(mIAppWidgetService, times(1)).getAppWidgetIds(any()); + verify(mAppWidgetManager, never()).updateAppWidget(anyInt(), any(RemoteViews.class)); + verify(mIAppWidgetService, never()).notifyAppWidgetViewDataChanged(any(), any(), anyInt()); } @Test @@ -122,7 +159,66 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { verify(mIAppWidgetService, times(1)).getAppWidgetIds(any()); verify(mIAppWidgetService, times(1)) .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt()); + verify(mIAppWidgetService, never()).updateAppWidgetIds(any(), any(), + any(RemoteViews.class)); + } + @Test + public void testNotifySingleConversationAppWidgetOnceIfNotificationPosted() + throws RemoteException { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0); + when(mINotificationManager.getConversations(true)).thenReturn( + new ParceledListSlice(getConversationWithShortcutId())); + int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT}; + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext); + SharedPreferences.Editor editor = sp.edit(); + editor.putString(String.valueOf(WIDGET_ID_WITH_SHORTCUT), SHORTCUT_ID); + editor.commit(); + when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray); + + NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder() + .setPkg(TEST_PACKAGE_A) + .setId(1)); + + verify(mIAppWidgetService, times(1)).getAppWidgetIds(any()); + verify(mIAppWidgetService, never()) + .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt()); + verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT), + any(RemoteViews.class)); + verify(mAppWidgetManager, never()).updateAppWidget(eq(WIDGET_ID_WITHOUT_SHORTCUT), + any(RemoteViews.class)); + } + + @Test + public void testNotifySingleConversationAppWidgetTwiceIfTwoNotificationsPosted() + throws RemoteException { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0); + when(mINotificationManager.getConversations(true)).thenReturn( + new ParceledListSlice(getConversationWithShortcutId())); + int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT}; + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext); + SharedPreferences.Editor editor = sp.edit(); + editor.putString(String.valueOf(WIDGET_ID_WITH_SHORTCUT), SHORTCUT_ID); + editor.commit(); + when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray); + + NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder() + .setPkg(TEST_PACKAGE_A) + .setId(1)); + mClock.advanceTime(4); + NotifEvent notif2 = mNoMan.postNotif(new NotificationEntryBuilder() + .setPkg(TEST_PACKAGE_B) + .setId(2)); + + verify(mIAppWidgetService, times(2)).getAppWidgetIds(any()); + verify(mIAppWidgetService, never()) + .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt()); + verify(mAppWidgetManager, times(2)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT), + any(RemoteViews.class)); + verify(mAppWidgetManager, never()).updateAppWidget(eq(WIDGET_ID_WITHOUT_SHORTCUT), + any(RemoteViews.class)); } @Test @@ -141,6 +237,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { verify(mIAppWidgetService, times(2)).getAppWidgetIds(any()); verify(mIAppWidgetService, times(2)) .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt()); + verify(mAppWidgetManager, never()).updateAppWidget(anyInt(), + any(RemoteViews.class)); } @Test @@ -157,6 +255,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { verify(mIAppWidgetService, times(2)).getAppWidgetIds(any()); verify(mIAppWidgetService, times(2)) .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt()); + verify(mAppWidgetManager, never()).updateAppWidget(anyInt(), + any(RemoteViews.class)); } @Test @@ -173,7 +273,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { verify(mIAppWidgetService, never()).getAppWidgetIds(any()); verify(mIAppWidgetService, never()).notifyAppWidgetViewDataChanged(any(), any(), anyInt()); - + verify(mAppWidgetManager, never()).updateAppWidget(anyInt(), + any(RemoteViews.class)); } @Test @@ -192,6 +293,17 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { verify(mIAppWidgetService, times(1)).getAppWidgetIds(any()); verify(mIAppWidgetService, times(1)) .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt()); + verify(mAppWidgetManager, never()).updateAppWidget(anyInt(), + any(RemoteViews.class)); + } + /** Returns a list of a single conversation associated with {@code SHORTCUT_ID}. */ + private List<ConversationChannelWrapper> getConversationWithShortcutId() { + List<ConversationChannelWrapper> convos = new ArrayList<>(); + ConversationChannelWrapper convo1 = new ConversationChannelWrapper(); + convo1.setShortcutInfo(new ShortcutInfo.Builder(mContext, SHORTCUT_ID).setLongLabel( + "name").build()); + convos.add(convo1); + return convos; } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt index 3e834986e383..a8b305614a4a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt @@ -343,6 +343,83 @@ class PrivacyItemControllerTest : SysuiTestCase() { assertTrue(values[values.size - 1].contains(expected.toLog())) } + @Test + fun testListRequestedForAllUsers() { + privacyItemController.addCallback(callback) + executor.runAllReady() + verify(appOpsController).getActiveAppOpsForUser(UserHandle.USER_ALL) + } + + @Test + fun testListFilterCurrentUser() { + val otherUser = CURRENT_USER_ID + 1 + val otherUserUid = otherUser * UserHandle.PER_USER_RANGE + `when`(userTracker.userProfiles).thenReturn(listOf(UserInfo(otherUser, "", 0))) + + doReturn(listOf( + AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, 0), + AppOpItem(AppOpsManager.OP_CAMERA, otherUserUid, TEST_PACKAGE_NAME, 0)) + ).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) + + privacyItemController.userTrackerCallback.onUserChanged(otherUser, mContext) + executor.runAllReady() + + privacyItemController.addCallback(callback) + executor.runAllReady() + + verify(callback).onPrivacyItemsChanged(capture(argCaptor)) + + assertEquals(1, argCaptor.value.size) + assertEquals(PrivacyType.TYPE_CAMERA, argCaptor.value[0].privacyType) + assertEquals(otherUserUid, argCaptor.value[0].application.uid) + } + + @Test + fun testAlwaysGetPhoneCameraOps() { + val otherUser = CURRENT_USER_ID + 1 + `when`(userTracker.userProfiles).thenReturn(listOf(UserInfo(otherUser, "", 0))) + + doReturn(listOf( + AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, 0), + AppOpItem(AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, 0), + AppOpItem(AppOpsManager.OP_PHONE_CALL_CAMERA, TEST_UID, TEST_PACKAGE_NAME, 0)) + ).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) + + privacyItemController.userTrackerCallback.onUserChanged(otherUser, mContext) + executor.runAllReady() + + privacyItemController.addCallback(callback) + executor.runAllReady() + + verify(callback).onPrivacyItemsChanged(capture(argCaptor)) + + assertEquals(1, argCaptor.value.size) + assertEquals(PrivacyType.TYPE_CAMERA, argCaptor.value[0].privacyType) + } + + @Test + fun testAlwaysGetPhoneMicOps() { + val otherUser = CURRENT_USER_ID + 1 + `when`(userTracker.userProfiles).thenReturn(listOf(UserInfo(otherUser, "", 0))) + + doReturn(listOf( + AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, 0), + AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, 0), + AppOpItem(AppOpsManager.OP_PHONE_CALL_MICROPHONE, TEST_UID, TEST_PACKAGE_NAME, 0)) + ).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) + + privacyItemController.userTrackerCallback.onUserChanged(otherUser, mContext) + executor.runAllReady() + + privacyItemController.addCallback(callback) + executor.runAllReady() + + verify(callback).onPrivacyItemsChanged(capture(argCaptor)) + + assertEquals(1, argCaptor.value.size) + assertEquals(PrivacyType.TYPE_MICROPHONE, argCaptor.value[0].privacyType) + } + private fun changeMicCamera(value: Boolean?) = changeProperty(MIC_CAMERA, value) private fun changeAll(value: Boolean?) = changeProperty(ALL_INDICATORS, value) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java index 3c9c9cca1619..353647b65cc0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java @@ -39,8 +39,11 @@ public class NotificationUiAdjustmentTest extends SysuiTestCase { @Test public void needReinflate_differentLength() { + // TODO(b/174258598) Please replace FLAG_MUTABLE_UNAUDITED below + // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent pendingIntent = - PendingIntent.getActivity(mContext, 0, new Intent(), 0); + PendingIntent.getActivity(mContext, 0, new Intent(), + PendingIntent.FLAG_MUTABLE_UNAUDITED); Notification.Action action = createActionBuilder("first", R.drawable.ic_corp_icon, pendingIntent).build(); assertThat(NotificationUiAdjustment.needReinflate( @@ -51,8 +54,11 @@ public class NotificationUiAdjustmentTest extends SysuiTestCase { @Test public void needReinflate_differentLabels() { + // TODO(b/174258598) Please replace FLAG_MUTABLE_UNAUDITED below + // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent pendingIntent = - PendingIntent.getActivity(mContext, 0, new Intent(), 0); + PendingIntent.getActivity(mContext, 0, new Intent(), + PendingIntent.FLAG_MUTABLE_UNAUDITED); Notification.Action firstAction = createActionBuilder("first", R.drawable.ic_corp_icon, pendingIntent).build(); Notification.Action secondAction = @@ -66,8 +72,11 @@ public class NotificationUiAdjustmentTest extends SysuiTestCase { @Test public void needReinflate_differentIcons() { + // TODO(b/174258598) Please replace FLAG_MUTABLE_UNAUDITED below + // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent pendingIntent = - PendingIntent.getActivity(mContext, 0, new Intent(), 0); + PendingIntent.getActivity(mContext, 0, new Intent(), + PendingIntent.FLAG_MUTABLE_UNAUDITED); Notification.Action firstAction = createActionBuilder("same", R.drawable.ic_corp_icon, pendingIntent).build(); Notification.Action secondAction = @@ -82,10 +91,14 @@ public class NotificationUiAdjustmentTest extends SysuiTestCase { @Test public void needReinflate_differentPendingIntent() { + // TODO(b/174258598) Please replace FLAG_MUTABLE_UNAUDITED below + // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent firstPendingIntent = - PendingIntent.getActivity(mContext, 0, new Intent(Intent.ACTION_VIEW), 0); + PendingIntent.getActivity(mContext, 0, new Intent(Intent.ACTION_VIEW), + PendingIntent.FLAG_MUTABLE_UNAUDITED); PendingIntent secondPendingIntent = - PendingIntent.getActivity(mContext, 0, new Intent(Intent.ACTION_PROCESS_TEXT), 0); + PendingIntent.getActivity(mContext, 0, new Intent(Intent.ACTION_PROCESS_TEXT), + PendingIntent.FLAG_MUTABLE_UNAUDITED); Notification.Action firstAction = createActionBuilder("same", R.drawable.ic_corp_icon, firstPendingIntent) .build(); @@ -101,8 +114,11 @@ public class NotificationUiAdjustmentTest extends SysuiTestCase { @Test public void needReinflate_differentChoices() { + // TODO(b/174258598) Please replace FLAG_MUTABLE_UNAUDITED below + // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent pendingIntent = - PendingIntent.getActivity(mContext, 0, new Intent(), 0); + PendingIntent.getActivity(mContext, 0, new Intent(), + PendingIntent.FLAG_MUTABLE_UNAUDITED); RemoteInput firstRemoteInput = createRemoteInput("same", "same", new CharSequence[] {"first"}); @@ -126,8 +142,11 @@ public class NotificationUiAdjustmentTest extends SysuiTestCase { @Test public void needReinflate_differentRemoteInputLabel() { + // TODO(b/174258598) Please replace FLAG_MUTABLE_UNAUDITED below + // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent pendingIntent = - PendingIntent.getActivity(mContext, 0, new Intent(), 0); + PendingIntent.getActivity(mContext, 0, new Intent(), + PendingIntent.FLAG_MUTABLE_UNAUDITED); RemoteInput firstRemoteInput = createRemoteInput("same", "first", new CharSequence[] {"same"}); @@ -151,8 +170,11 @@ public class NotificationUiAdjustmentTest extends SysuiTestCase { @Test public void needReinflate_negative() { + // TODO(b/174258598) Please replace FLAG_MUTABLE_UNAUDITED below + // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent pendingIntent = - PendingIntent.getActivity(mContext, 0, new Intent(), 0); + PendingIntent.getActivity(mContext, 0, new Intent(), + PendingIntent.FLAG_MUTABLE_UNAUDITED); RemoteInput firstRemoteInput = createRemoteInput("same", "same", new CharSequence[] {"same"}); RemoteInput secondRemoteInput = diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java index 0be9f7de5825..5fc01ccd96b4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java @@ -629,7 +629,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase { return new Notification.Action.Builder( Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon), "action", - PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0)).build(); + PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), + PendingIntent.FLAG_IMMUTABLE)).build(); } private static class FakeNotificationLifetimeExtender implements NotificationLifetimeExtender { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java index 1a022ec7c87d..241451edf698 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java @@ -233,7 +233,8 @@ public class NotificationEntryTest extends SysuiTestCase { return new Notification.Action.Builder( Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon), title, - PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0)) + PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), + PendingIntent.FLAG_IMMUTABLE)) .setContextual(true) .build(); } @@ -242,7 +243,8 @@ public class NotificationEntryTest extends SysuiTestCase { return new Notification.Action.Builder( Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon), title, - PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0)).build(); + PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), + PendingIntent.FLAG_IMMUTABLE)).build(); } private ArrayList<Notification.Action> createActions(String... titles) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java index e254cd2c82a7..60c3bc874235 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java @@ -476,7 +476,8 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase { private NotificationEntry createBubble() { Notification.BubbleMetadata data = new Notification.BubbleMetadata.Builder( - PendingIntent.getActivity(mContext, 0, new Intent(), 0), + PendingIntent.getActivity(mContext, 0, new Intent(), + PendingIntent.FLAG_MUTABLE), Icon.createWithResource(mContext.getResources(), R.drawable.android)) .build(); Notification n = new Notification.Builder(getContext(), "a") diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java index 738ce537e4c5..9d87579ee154 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java @@ -28,7 +28,6 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.eq; @@ -56,6 +55,7 @@ import android.widget.TextView; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.statusbar.notification.AssistantFeedbackController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -65,8 +65,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; - -import java.util.concurrent.CountDownLatch; +import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidTestingRunner.class) @@ -78,18 +77,24 @@ public class FeedbackInfoTest extends SysuiTestCase { private FeedbackInfo mFeedbackInfo; private final PackageManager mMockPackageManager = mock(PackageManager.class); private final NotificationGuts mGutsParent = mock(NotificationGuts.class); + private final ExpandableNotificationRow mMockNotificationRow = + mock(ExpandableNotificationRow.class); private StatusBarNotification mSbn; @Mock private NotificationEntryManager mNotificationEntryManager; @Mock private IStatusBarService mStatusBarService; + @Mock + private NotificationGutsManager mNotificationGutsManager; @Before public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager); mDependency.injectTestDependency(IStatusBarService.class, mStatusBarService); + mDependency.injectTestDependency(NotificationGutsManager.class, mNotificationGutsManager); // Inflate the layout final LayoutInflater layoutInflater = LayoutInflater.from(mContext); @@ -108,13 +113,14 @@ public class FeedbackInfoTest extends SysuiTestCase { mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0, new Notification(), UserHandle.CURRENT, null, 0); + } @Test public void testBindNotification_SetsTextApplicationName() { when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name"); mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), - mock(AssistantFeedbackController.class)); + mMockNotificationRow, mock(AssistantFeedbackController.class)); final TextView textView = mFeedbackInfo.findViewById(R.id.pkg_name); assertTrue(textView.getText().toString().contains("App Name")); } @@ -125,27 +131,16 @@ public class FeedbackInfoTest extends SysuiTestCase { when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class))) .thenReturn(iconDrawable); mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), - mock(AssistantFeedbackController.class)); + mMockNotificationRow, mock(AssistantFeedbackController.class)); final ImageView iconView = mFeedbackInfo.findViewById(R.id.pkg_icon); assertEquals(iconDrawable, iconView.getDrawable()); } @Test - public void testOk() { - final CountDownLatch latch = new CountDownLatch(1); - mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), - mock(AssistantFeedbackController.class)); - - final View okButton = mFeedbackInfo.findViewById(R.id.ok); - okButton.performClick(); - assertEquals(1, latch.getCount()); - verify(mGutsParent, times(1)).closeControls(any(), anyBoolean()); - } - - @Test public void testPrompt_silenced() { mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT, - IMPORTANCE_LOW, RANKING_UNCHANGED), mock(AssistantFeedbackController.class)); + IMPORTANCE_LOW, RANKING_UNCHANGED), mMockNotificationRow, + mock(AssistantFeedbackController.class)); TextView prompt = mFeedbackInfo.findViewById(R.id.prompt); assertEquals("This notification was silenced by the system. Was this correct?", prompt.getText()); @@ -154,7 +149,8 @@ public class FeedbackInfoTest extends SysuiTestCase { @Test public void testPrompt_promoted_importance() { mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT, - IMPORTANCE_HIGH, RANKING_UNCHANGED), mock(AssistantFeedbackController.class)); + IMPORTANCE_HIGH, RANKING_UNCHANGED), mMockNotificationRow, + mock(AssistantFeedbackController.class)); TextView prompt = mFeedbackInfo.findViewById(R.id.prompt); assertEquals("This notification was promoted by the system. Was this correct?", prompt.getText()); @@ -163,7 +159,8 @@ public class FeedbackInfoTest extends SysuiTestCase { @Test public void testPrompt_promoted_ranking() { mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT, - IMPORTANCE_DEFAULT, RANKING_PROMOTED), mock(AssistantFeedbackController.class)); + IMPORTANCE_DEFAULT, RANKING_PROMOTED), mMockNotificationRow, + mock(AssistantFeedbackController.class)); TextView prompt = mFeedbackInfo.findViewById(R.id.prompt); assertEquals("This notification was promoted by the system. Was this correct?", prompt.getText()); @@ -172,7 +169,8 @@ public class FeedbackInfoTest extends SysuiTestCase { @Test public void testPrompt_demoted_importance() { mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_LOW, - IMPORTANCE_MIN, RANKING_UNCHANGED), mock(AssistantFeedbackController.class)); + IMPORTANCE_MIN, RANKING_UNCHANGED), mMockNotificationRow, + mock(AssistantFeedbackController.class)); TextView prompt = mFeedbackInfo.findViewById(R.id.prompt); assertEquals("This notification was demoted by the system. Was this correct?", prompt.getText()); @@ -181,12 +179,43 @@ public class FeedbackInfoTest extends SysuiTestCase { @Test public void testPrompt_demoted_ranking() { mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT, - IMPORTANCE_DEFAULT, RANKING_DEMOTED), mock(AssistantFeedbackController.class)); + IMPORTANCE_DEFAULT, RANKING_DEMOTED), mMockNotificationRow, + mock(AssistantFeedbackController.class)); TextView prompt = mFeedbackInfo.findViewById(R.id.prompt); assertEquals("This notification was demoted by the system. Was this correct?", prompt.getText()); } + @Test + public void testPositiveFeedback() { + mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow, + mock(AssistantFeedbackController.class)); + + final View yes = mFeedbackInfo.findViewById(R.id.yes); + yes.performClick(); + verify(mGutsParent, times(1)).closeControls(yes, false); + } + + @Test + public void testNegativeFeedback() { + when(mNotificationGutsManager.openGuts( + any(View.class), + anyInt(), + anyInt(), + any(NotificationMenuRowPlugin.MenuItem.class))) + .thenReturn(true); + + mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow, + mock(AssistantFeedbackController.class)); + + final View no = mFeedbackInfo.findViewById(R.id.no); + no.performClick(); + verify(mGutsParent, times(1)).closeControls(no, false); + verify(mNotificationGutsManager, times(1)).openGuts( + eq(mMockNotificationRow), eq(0), eq(0), + any()); + } + private NotificationEntry getEntry(int oldImportance, int newImportance, int rankingAdjustment) { NotificationChannel channel = new NotificationChannel("id", "name", oldImportance); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java index d08b2b78d00b..2101ea1766a1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java @@ -81,12 +81,15 @@ public class NotificationContentViewTest extends SysuiTestCase { View mockContracted = mock(NotificationHeaderView.class); when(mockContracted.findViewById(com.android.internal.R.id.feedback)) .thenReturn(mockContracted); + when(mockContracted.getContext()).thenReturn(mContext); View mockExpanded = mock(NotificationHeaderView.class); when(mockExpanded.findViewById(com.android.internal.R.id.feedback)) .thenReturn(mockExpanded); + when(mockExpanded.getContext()).thenReturn(mContext); View mockHeadsUp = mock(NotificationHeaderView.class); when(mockHeadsUp.findViewById(com.android.internal.R.id.feedback)) .thenReturn(mockHeadsUp); + when(mockHeadsUp.getContext()).thenReturn(mContext); mView.setContractedChild(mockContracted); mView.setExpandedChild(mockExpanded); @@ -107,18 +110,21 @@ public class NotificationContentViewTest extends SysuiTestCase { when(mockContracted.animate()).thenReturn(mock(ViewPropertyAnimator.class)); when(mockContracted.findViewById(com.android.internal.R.id.expand_button)).thenReturn( mockContractedEB); + when(mockContracted.getContext()).thenReturn(mContext); View mockExpandedEB = mock(NotificationExpandButton.class); View mockExpanded = mock(NotificationHeaderView.class); when(mockExpanded.animate()).thenReturn(mock(ViewPropertyAnimator.class)); when(mockExpanded.findViewById(com.android.internal.R.id.expand_button)).thenReturn( mockExpandedEB); + when(mockExpanded.getContext()).thenReturn(mContext); View mockHeadsUpEB = mock(NotificationExpandButton.class); View mockHeadsUp = mock(NotificationHeaderView.class); when(mockHeadsUp.animate()).thenReturn(mock(ViewPropertyAnimator.class)); when(mockHeadsUp.findViewById(com.android.internal.R.id.expand_button)).thenReturn( mockHeadsUpEB); + when(mockHeadsUp.getContext()).thenReturn(mContext); // Set up all 3 child forms mView.setContractedChild(mockContracted); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java index f7dfe0b434a7..291b223d72bb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java @@ -214,7 +214,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mEntry = new NotificationEntryBuilder().setSbn(mSbn).setShortcutInfo(mShortcutInfo).build(); PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, - new Intent(mContext, BubblesTestActivity.class), 0); + new Intent(mContext, BubblesTestActivity.class), + PendingIntent.FLAG_MUTABLE); mBubbleSbn = new SbnBuilder(mSbn).setBubbleMetadata( new Notification.BubbleMetadata.Builder(bubbleIntent, Icon.createWithResource(mContext, R.drawable.android)).build()) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java index 7470a13ae39e..6fcc7fa9376c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java @@ -455,7 +455,8 @@ public class NotificationTestHelper { private BubbleMetadata makeBubbleMetadata(PendingIntent deleteIntent) { Intent target = new Intent(mContext, BubblesTestActivity.class); - PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target, 0); + PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target, + PendingIntent.FLAG_MUTABLE); return new BubbleMetadata.Builder(bubbleIntent, Icon.createWithResource(mContext, R.drawable.android)) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java index 085bd900debc..93a9e597ca90 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.row.wrapper; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import android.content.Context; import android.testing.AndroidTestingRunner; @@ -49,6 +50,7 @@ public class NotificationViewWrapperTest extends SysuiTestCase { public void setup() throws Exception { allowTestableLooperAsMainThread(); mView = mock(View.class); + when(mView.getContext()).thenReturn(mContext); NotificationTestHelper helper = new NotificationTestHelper( mContext, mDependency, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java index 83ef87a1066c..c7c1823f6a29 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java @@ -19,7 +19,6 @@ package com.android.systemui.statusbar.phone; import static com.google.common.truth.Truth.assertThat; import android.testing.AndroidTestingRunner; -import android.testing.TestableLooper; import androidx.test.filters.SmallTest; @@ -31,7 +30,6 @@ import org.junit.runner.RunWith; @SmallTest @RunWith(AndroidTestingRunner.class) -@TestableLooper.RunWithLooper public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { private static final int SCREEN_HEIGHT = 2000; @@ -53,6 +51,7 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { private int mPreferredClockY; private boolean mHasCustomClock; private boolean mHasVisibleNotifs; + private float mQsExpansion; @Before public void setUp() { @@ -355,6 +354,17 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { } @Test + public void clockHiddenWhenQsIsExpanded() { + // GIVEN on the lock screen with a custom clock and visible notifications + givenLockScreen(); + mQsExpansion = 1; + // WHEN the clock position algorithm is run + positionClock(); + // THEN the clock Y position is the middle of the screen (SCREEN_HEIGHT / 2). + assertThat(mClockPosition.clockAlpha).isEqualTo(TRANSPARENT); + } + + @Test public void preferredCustomClockPositionWithVisibleNotificationsOnAod() { // GIVEN on the lock screen with a custom clock and visible notifications givenAOD(); @@ -384,7 +394,7 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight, mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight, mPreferredClockY, mHasCustomClock, mHasVisibleNotifs, mDark, ZERO_DRAG, false /* bypassEnabled */, - 0 /* unlockedStackScrollerPadding */, false /* udfpsEnrolled */); + 0 /* unlockedStackScrollerPadding */, false /* udfpsEnrolled */, mQsExpansion); mClockPositionAlgorithm.run(mClockPosition); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java index d4a94a19af4f..d452861c31c0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java @@ -199,6 +199,8 @@ public class NotificationPanelViewTest extends SysuiTestCase { @Mock private AuthController mAuthController; @Mock + private ScrimController mScrimController; + @Mock private MediaDataManager mMediaDataManager; private NotificationPanelViewController mNotificationPanelViewController; @@ -279,6 +281,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { mNotificationAreaController, mAuthController, new QSDetailDisplayer(), + mScrimController, mMediaDataManager); mNotificationPanelViewController.initDependencies( mStatusBar, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java index eaf31ed17bb2..342b2f57396e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java @@ -249,6 +249,20 @@ public class ScrimControllerTest extends SysuiTestCase { } @Test + public void transitionToShadeLocked() { + mScrimController.transitionTo(ScrimState.SHADE_LOCKED); + finishAnimationsImmediately(); + + assertScrimAlpha(TRANSPARENT /* front */, + OPAQUE /* back */, + TRANSPARENT /* bubble */); + + assertScrimTint(false /* front */, + false /* behind */, + false /* bubble */); + } + + @Test public void transitionToOff() { mScrimController.transitionTo(ScrimState.OFF); finishAnimationsImmediately(); @@ -464,7 +478,7 @@ public class ScrimControllerTest extends SysuiTestCase { // Front scrim should be transparent // Back scrim should be visible without tint assertScrimAlpha(TRANSPARENT /* front */, - SEMI_TRANSPARENT /* back */, + OPAQUE /* back */, TRANSPARENT /* bubble */); assertScrimTint(false /* front */, @@ -478,7 +492,7 @@ public class ScrimControllerTest extends SysuiTestCase { finishAnimationsImmediately(); // Front scrim should be transparent // Back scrim should be visible without tint - assertScrimAlpha(SEMI_TRANSPARENT /* front */, + assertScrimAlpha(OPAQUE /* front */, TRANSPARENT /* back */, TRANSPARENT /* bubble */); assertScrimTint(false /* front */, @@ -519,11 +533,11 @@ public class ScrimControllerTest extends SysuiTestCase { Assert.assertEquals(ScrimController.TRANSPARENT, mScrimInFront.getViewAlpha(), 0.0f); // Back scrim should be visible - Assert.assertEquals(ScrimController.BLUR_SCRIM_ALPHA, + Assert.assertEquals(ScrimController.BUSY_SCRIM_ALPHA, mScrimBehind.getViewAlpha(), 0.0f); // Bubble scrim should be visible - Assert.assertEquals(ScrimController.BLUR_SCRIM_ALPHA, - mScrimBehind.getViewAlpha(), 0.0f); + Assert.assertEquals(ScrimController.BUBBLE_SCRIM_ALPHA, + mScrimForBubble.getViewAlpha(), 0.0f); } @Test @@ -564,6 +578,15 @@ public class ScrimControllerTest extends SysuiTestCase { } @Test + public void qsExpansion() { + reset(mScrimBehind); + mScrimController.setQsExpansion(1f); + finishAnimationsImmediately(); + + assertScrimAlpha(TRANSPARENT, OPAQUE, TRANSPARENT); + } + + @Test public void panelExpansionAffectsAlpha() { mScrimController.setPanelExpansion(0f); mScrimController.setPanelExpansion(0.5f); @@ -888,7 +911,7 @@ public class ScrimControllerTest extends SysuiTestCase { HashSet<ScrimState> regularStates = new HashSet<>(Arrays.asList( ScrimState.UNINITIALIZED, ScrimState.KEYGUARD, ScrimState.BOUNCER, ScrimState.BOUNCER_SCRIMMED, ScrimState.BRIGHTNESS_MIRROR, ScrimState.UNLOCKED, - ScrimState.BUBBLE_EXPANDED)); + ScrimState.BUBBLE_EXPANDED, ScrimState.SHADE_LOCKED)); for (ScrimState state : ScrimState.values()) { if (!lowPowerModeStates.contains(state) && !regularStates.contains(state)) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 5416f75dffff..6fb4ebaba1b6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -151,6 +151,7 @@ import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.splitscreen.SplitScreen; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -886,6 +887,7 @@ public class StatusBarTest extends SysuiTestCase { verify(mDozeServiceHost).setDozeSuppressed(false); } + @Ignore // TODO (b/175240607) - Figure out if the device will actually dial 911. @Test public void onEmergencyActionLaunchGesture_launchesEmergencyIntent() { ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); @@ -896,7 +898,6 @@ public class StatusBarTest extends SysuiTestCase { verify(statusBarSpy).startActivity(intentCaptor.capture(), eq(true)); Intent sentIntent = intentCaptor.getValue(); assertEquals(sentIntent.getAction(), EmergencyGesture.ACTION_LAUNCH_EMERGENCY); - } public static class TestableNotificationInterruptStateProviderImpl extends diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java index 23fa6fd5e4ca..2577dbdbb593 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java @@ -16,7 +16,11 @@ package com.android.systemui.statusbar.policy; +import static android.os.BatteryManager.EXTRA_PRESENT; + +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Intent; @@ -31,6 +35,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.power.EnhancedEstimates; +import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; import org.junit.Assert; import org.junit.Before; @@ -98,4 +103,36 @@ public class BatteryControllerTest extends SysuiTestCase { Assert.assertFalse(mBatteryController.isAodPowerSave()); } + @Test + public void testBatteryPresentState_notPresent() { + // GIVEN a battery state callback listening for changes + BatteryStateChangeCallback cb = mock(BatteryStateChangeCallback.class); + mBatteryController.addCallback(cb); + + // WHEN the state of the battery becomes unknown + Intent i = new Intent(Intent.ACTION_BATTERY_CHANGED); + i.putExtra(EXTRA_PRESENT, false); + mBatteryController.onReceive(getContext(), i); + + // THEN the callback is notified + verify(cb, atLeastOnce()).onBatteryUnknownStateChanged(true); + } + + @Test + public void testBatteryPresentState_callbackAddedAfterStateChange() { + // GIVEN a battery state callback + BatteryController.BatteryStateChangeCallback cb = + mock(BatteryController.BatteryStateChangeCallback.class); + + // GIVEN the state has changed before adding a new callback + Intent i = new Intent(Intent.ACTION_BATTERY_CHANGED); + i.putExtra(EXTRA_PRESENT, false); + mBatteryController.onReceive(getContext(), i); + + // WHEN a callback is added + mBatteryController.addCallback(cb); + + // THEN it is informed about the battery state + verify(cb, atLeastOnce()).onBatteryUnknownStateChanged(true); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index 138236af70ce..ce9ca9d633fd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -61,6 +61,7 @@ import android.util.Log; import androidx.test.InstrumentationRegistry; import com.android.settingslib.graph.SignalDrawable; +import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults; import com.android.settingslib.net.DataUsageController; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; @@ -70,7 +71,6 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceP import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config; -import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults; import org.junit.Before; import org.junit.Rule; @@ -225,7 +225,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { setDefaultSubId(mSubId); setSubscriptions(mSubId); mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId); - mPhoneStateListener = mMobileSignalController.mPhoneStateListener; + mPhoneStateListener = mMobileSignalController.mMobileStatusTracker.getPhoneStateListener(); ArgumentCaptor<ConnectivityManager.NetworkCallback> callbackArg = ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); diff --git a/packages/Tethering/OWNERS b/packages/Tethering/OWNERS new file mode 100644 index 000000000000..aa87958f1d53 --- /dev/null +++ b/packages/Tethering/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/net/OWNERS diff --git a/packages/VpnDialogs/OWNERS b/packages/VpnDialogs/OWNERS new file mode 100644 index 000000000000..aa87958f1d53 --- /dev/null +++ b/packages/VpnDialogs/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/net/OWNERS diff --git a/packages/WAPPushManager/OWNERS b/packages/WAPPushManager/OWNERS new file mode 100644 index 000000000000..640baf2297b4 --- /dev/null +++ b/packages/WAPPushManager/OWNERS @@ -0,0 +1 @@ +include /telephony/OWNERS diff --git a/packages/WallpaperBackup/OWNERS b/packages/WallpaperBackup/OWNERS new file mode 100644 index 000000000000..d99779e3d9da --- /dev/null +++ b/packages/WallpaperBackup/OWNERS @@ -0,0 +1 @@ +include /services/backup/OWNERS diff --git a/packages/WallpaperCropper/OWNERS b/packages/WallpaperCropper/OWNERS new file mode 100644 index 000000000000..8ff0f74202f8 --- /dev/null +++ b/packages/WallpaperCropper/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/wallpaper/OWNERS diff --git a/packages/WindowManager/OWNERS b/packages/WindowManager/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/packages/WindowManager/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/packages/overlays/OWNERS b/packages/overlays/OWNERS new file mode 100644 index 000000000000..afb98d416762 --- /dev/null +++ b/packages/overlays/OWNERS @@ -0,0 +1 @@ +include /core/java/android/content/om/OWNERS diff --git a/packages/services/PacProcessor/OWNERS b/packages/services/PacProcessor/OWNERS new file mode 100644 index 000000000000..aa87958f1d53 --- /dev/null +++ b/packages/services/PacProcessor/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/net/OWNERS diff --git a/packages/services/Proxy/OWNERS b/packages/services/Proxy/OWNERS new file mode 100644 index 000000000000..aa87958f1d53 --- /dev/null +++ b/packages/services/Proxy/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/net/OWNERS diff --git a/proto/src/OWNERS b/proto/src/OWNERS new file mode 100644 index 000000000000..e7ddf8691463 --- /dev/null +++ b/proto/src/OWNERS @@ -0,0 +1,2 @@ +per-file gnss.proto = file:/services/core/java/com/android/server/location/OWNERS +per-file wifi.proto = file:/wifi/OWNERS diff --git a/proto/src/metrics_constants/OWNERS b/proto/src/metrics_constants/OWNERS index 7009282b66e1..ab4d808f5ff0 100644 --- a/proto/src/metrics_constants/OWNERS +++ b/proto/src/metrics_constants/OWNERS @@ -1,4 +1,4 @@ -cwren@android.com +cwren@google.com yanglu@google.com yaochen@google.com yro@google.com diff --git a/samples/training/network-usage/OWNERS b/samples/training/network-usage/OWNERS new file mode 100644 index 000000000000..aa87958f1d53 --- /dev/null +++ b/samples/training/network-usage/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/net/OWNERS diff --git a/services/OWNERS b/services/OWNERS new file mode 100644 index 000000000000..88d0b61a2ab6 --- /dev/null +++ b/services/OWNERS @@ -0,0 +1 @@ +per-file Android.bp = file:platform/build/soong:/OWNERS diff --git a/services/api/OWNERS b/services/api/OWNERS new file mode 100644 index 000000000000..a6093900c635 --- /dev/null +++ b/services/api/OWNERS @@ -0,0 +1,4 @@ +per-file Android.bp = file:platform/build/soong:/OWNERS + +# API changes are managed via Prolog rules, not OWNERS +* diff --git a/services/appprediction/OWNERS b/services/appprediction/OWNERS new file mode 100644 index 000000000000..3a5d23d6928f --- /dev/null +++ b/services/appprediction/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/appprediction/OWNERS diff --git a/services/autofill/OWNERS b/services/autofill/OWNERS new file mode 100644 index 000000000000..c52751d79227 --- /dev/null +++ b/services/autofill/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/autofill/OWNERS diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 33d13de8be4b..bc59602d3378 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -29,8 +29,6 @@ import static com.android.server.autofill.Helper.sVerbose; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManagerInternal; -import android.app.ActivityTaskManager; -import android.app.IActivityTaskManager; import android.content.ComponentName; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; @@ -86,6 +84,7 @@ import com.android.server.autofill.ui.AutoFillUI; import com.android.server.contentcapture.ContentCaptureManagerInternal; import com.android.server.infra.AbstractPerUserSystemService; import com.android.server.inputmethod.InputMethodManagerInternal; +import com.android.server.wm.ActivityTaskManagerInternal; import java.io.PrintWriter; import java.util.ArrayList; @@ -1638,19 +1637,16 @@ final class AutofillManagerServiceImpl } } - final IActivityTaskManager atm = ActivityTaskManager.getService(); + final ActivityTaskManagerInternal atmInternal = LocalServices.getService( + ActivityTaskManagerInternal.class); // Only remove sessions which's activities are not known to the activity manager anymore for (int i = 0; i < numSessionsToRemove; i++) { - try { - // The activity manager cannot resolve activities that have been removed - if (atm.getActivityClassForToken(sessionsToRemove.valueAt(i)) != null) { - sessionsToRemove.removeAt(i); - i--; - numSessionsToRemove--; - } - } catch (RemoteException e) { - Slog.w(TAG, "Cannot figure out if activity is finished", e); + // The activity task manager cannot resolve activities that have been removed. + if (atmInternal.getActivityName(sessionsToRemove.valueAt(i)) != null) { + sessionsToRemove.removeAt(i); + i--; + numSessionsToRemove--; } } diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index ac6ed440093d..6c30999f63a4 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -512,7 +512,7 @@ public class BackupManagerService extends IBackupManager.Stub { int callingUid = Binder.getCallingUid(); if (CompatChanges.isChangeEnabled( BackupManager.IS_BACKUP_SERVICE_ACTIVE_ENFORCE_PERMISSION_IN_SERVICE, callingUid)) { - mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "isBackupServiceActive"); } synchronized (mStateLock) { diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index 5fedf9f89fc1..0a80b02a964c 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -31,8 +31,12 @@ import static java.util.concurrent.TimeUnit.MINUTES; import android.annotation.CheckResult; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.app.AppOpsManager; import android.app.PendingIntent; +import android.app.role.RoleManager; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; import android.companion.Association; import android.companion.AssociationRequest; import android.companion.CompanionDeviceManager; @@ -47,6 +51,7 @@ import android.content.pm.FeatureInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; +import android.content.pm.UserInfo; import android.net.NetworkPolicyManager; import android.os.Binder; import android.os.Environment; @@ -62,6 +67,7 @@ import android.os.ServiceManager; import android.os.ShellCallback; import android.os.ShellCommand; import android.os.UserHandle; +import android.os.UserManager; import android.provider.Settings; import android.provider.SettingsStringUtil.ComponentNameSet; import android.text.BidiFormatter; @@ -70,6 +76,7 @@ import android.util.AtomicFile; import android.util.ExceptionUtils; import android.util.Log; import android.util.Slog; +import android.util.SparseArray; import android.util.Xml; import com.android.internal.annotations.GuardedBy; @@ -116,12 +123,16 @@ import java.util.function.Function; //TODO on associate called again after configuration change -> replace old callback with new //TODO avoid leaking calling activity in IFindDeviceCallback (see PrintManager#print for example) /** @hide */ +@SuppressLint("LongLogTag") public class CompanionDeviceManagerService extends SystemService implements Binder.DeathRecipient { private static final ComponentName SERVICE_TO_BIND_TO = ComponentName.createRelative( CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME, ".DeviceDiscoveryService"); + // 10 min + public static final int DEVICE_DISCONNECT_PROFILE_REVOKE_DELAY_MS = 10 * 60 * 1000; + private static final boolean DEBUG = false; private static final String LOG_TAG = "CompanionDeviceManagerService"; @@ -132,6 +143,8 @@ public class CompanionDeviceManagerService extends SystemService implements Bind private static final String XML_TAG_ASSOCIATION = "association"; private static final String XML_ATTR_PACKAGE = "package"; private static final String XML_ATTR_DEVICE = "device"; + private static final String XML_ATTR_PROFILE = "profile"; + private static final String XML_ATTR_PERSISTENT_PROFILE_GRANTS = "persistent_profile_grants"; private static final String XML_FILE_NAME = "companion_device_manager_associations.xml"; private final CompanionDeviceManagerImpl mImpl; @@ -139,21 +152,29 @@ public class CompanionDeviceManagerService extends SystemService implements Bind private PowerWhitelistManager mPowerWhitelistManager; private PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>> mServiceConnectors; private IAppOpsService mAppOpsManager; + private RoleManager mRoleManager; + private BluetoothAdapter mBluetoothAdapter; private IFindDeviceCallback mFindDeviceCallback; private AssociationRequest mRequest; private String mCallingPackage; private AndroidFuture<Association> mOngoingDeviceDiscovery; + private BluetoothDeviceConnectedListener mBluetoothDeviceConnectedListener = + new BluetoothDeviceConnectedListener(); + private List<String> mCurrentlyConnectedDevices = new ArrayList<>(); + private final Object mLock = new Object(); + /** userId -> [association] */ @GuardedBy("mLock") - private @Nullable Set<Association> mCachedAssociations = null; + private @Nullable SparseArray<Set<Association>> mCachedAssociations = new SparseArray<>(); public CompanionDeviceManagerService(Context context) { super(context); mImpl = new CompanionDeviceManagerImpl(); mPowerWhitelistManager = context.getSystemService(PowerWhitelistManager.class); + mRoleManager = context.getSystemService(RoleManager.class); mAppOpsManager = IAppOpsService.Stub.asInterface( ServiceManager.getService(Context.APP_OPS_SERVICE)); @@ -184,9 +205,9 @@ public class CompanionDeviceManagerService extends SystemService implements Bind @Override public void onPackageModified(String packageName) { int userId = getChangingUserId(); - if (!ArrayUtils.isEmpty(getAllAssociations(userId, packageName))) { - updateSpecialAccessPermissionForAssociatedPackage(packageName, userId); - } + forEach(getAllAssociations(userId, packageName), association -> { + updateSpecialAccessPermissionForAssociatedPackage(association); + }); } }.register(getContext(), FgThread.get().getLooper(), UserHandle.ALL, true); @@ -198,6 +219,18 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } @Override + public void onBootPhase(int phase) { + if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + if (mBluetoothAdapter != null) { + mBluetoothAdapter.registerBluetoothConnectionCallback( + getContext().getMainExecutor(), + mBluetoothDeviceConnectedListener); + } + } + } + + @Override public void onUserUnlocking(@NonNull TargetUser user) { int userHandle = user.getUserIdentifier(); Set<Association> associations = getAllAssociations(userHandle); @@ -495,12 +528,14 @@ public class CompanionDeviceManagerService extends SystemService implements Bind fout.append("Companion Device Associations:").append('\n'); synchronized (mLock) { - forEach(mCachedAssociations, a -> { - fout.append(" ") - .append("u").append("" + a.getUserId()).append(": ") - .append(a.getPackageName()).append(" - ") - .append(a.getDeviceMacAddress()).append('\n'); - }); + for (UserInfo user : getAllUsers()) { + forEach(mCachedAssociations.get(user.id), a -> { + fout.append(" ") + .append("u").append("" + a.getUserId()).append(": ") + .append(a.getPackageName()).append(" - ") + .append(a.getDeviceMacAddress()).append('\n'); + }); + } } } } @@ -513,32 +548,34 @@ public class CompanionDeviceManagerService extends SystemService implements Bind return Binder.getCallingUid() == Process.SYSTEM_UID; } - void addAssociation(int userId, String packageName, String deviceAddress) { - addAssociation(new Association(userId, deviceAddress, packageName)); - } - void addAssociation(Association association) { - updateSpecialAccessPermissionForAssociatedPackage( - association.getPackageName(), association.getUserId()); + updateSpecialAccessPermissionForAssociatedPackage(association); recordAssociation(association); } void removeAssociation(int userId, String pkg, String deviceMacAddress) { - updateAssociations(associations -> CollectionUtils.remove(associations, - new Association(userId, deviceMacAddress, pkg))); + updateAssociations(associations -> CollectionUtils.filter(associations, association -> { + return association.getUserId() != userId + || !Objects.equals(association.getDeviceMacAddress(), deviceMacAddress) + || !Objects.equals(association.getPackageName(), pkg); + })); } - private void updateSpecialAccessPermissionForAssociatedPackage(String packageName, int userId) { - PackageInfo packageInfo = getPackageInfo(packageName, userId); + private void updateSpecialAccessPermissionForAssociatedPackage(Association association) { + PackageInfo packageInfo = getPackageInfo( + association.getPackageName(), + association.getUserId()); if (packageInfo == null) { return; } Binder.withCleanCallingIdentity(obtainRunnable(CompanionDeviceManagerService:: - updateSpecialAccessPermissionAsSystem, this, packageInfo).recycleOnUse()); + updateSpecialAccessPermissionAsSystem, this, association, packageInfo) + .recycleOnUse()); } - private void updateSpecialAccessPermissionAsSystem(PackageInfo packageInfo) { + private void updateSpecialAccessPermissionAsSystem( + Association association, PackageInfo packageInfo) { if (containsEither(packageInfo.requestedPermissions, android.Manifest.permission.RUN_IN_BACKGROUND, android.Manifest.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND)) { @@ -602,10 +639,6 @@ public class CompanionDeviceManagerService extends SystemService implements Bind updateAssociations(associations -> CollectionUtils.add(associations, association)); } - private void recordAssociation(String privilegedPackage, String deviceAddress) { - recordAssociation(new Association(getCallingUserId(), deviceAddress, privilegedPackage)); - } - private void updateAssociations(Function<Set<Association>, Set<Association>> update) { updateAssociations(update, getCallingUserId()); } @@ -625,7 +658,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind if (DEBUG) { Slog.i(LOG_TAG, "Updating associations: " + old + " --> " + associations); } - mCachedAssociations = Collections.unmodifiableSet(associations); + mCachedAssociations.put(userId, Collections.unmodifiableSet(associations)); BackgroundThread.getHandler().sendMessage(PooledLambda.obtainMessage( CompanionDeviceManagerService::persistAssociations, this, associations, userId)); @@ -651,10 +684,17 @@ public class CompanionDeviceManagerService extends SystemService implements Bind xml.startTag(null, XML_TAG_ASSOCIATIONS); forEach(associations, association -> { - xml.startTag(null, XML_TAG_ASSOCIATION) + XmlSerializer tag = xml.startTag(null, XML_TAG_ASSOCIATION) .attribute(null, XML_ATTR_PACKAGE, association.getPackageName()) - .attribute(null, XML_ATTR_DEVICE, association.getDeviceMacAddress()) - .endTag(null, XML_TAG_ASSOCIATION); + .attribute(null, XML_ATTR_DEVICE, + association.getDeviceMacAddress()); + if (association.getDeviceProfile() != null) { + tag.attribute(null, XML_ATTR_PROFILE, association.getDeviceProfile()); + tag.attribute(null, XML_ATTR_PERSISTENT_PROFILE_GRANTS, + Boolean.toString( + association.isKeepProfilePrivilegesWhenDeviceAway())); + } + tag.endTag(null, XML_TAG_ASSOCIATION); }); xml.endTag(null, XML_TAG_ASSOCIATIONS); @@ -678,17 +718,21 @@ public class CompanionDeviceManagerService extends SystemService implements Bind @Nullable private Set<Association> getAllAssociations(int userId) { synchronized (mLock) { - if (mCachedAssociations == null) { - mCachedAssociations = Collections.unmodifiableSet( - emptyIfNull(readAllAssociations(userId))); + if (mCachedAssociations.get(userId) == null) { + mCachedAssociations.put(userId, Collections.unmodifiableSet( + emptyIfNull(readAllAssociations(userId)))); if (DEBUG) { Slog.i(LOG_TAG, "Read associations from disk: " + mCachedAssociations); } } - return mCachedAssociations; + return mCachedAssociations.get(userId); } } + private List<UserInfo> getAllUsers() { + return getContext().getSystemService(UserManager.class).getUsers(); + } + @Nullable private Set<Association> getAllAssociations(int userId, @Nullable String packageFilter) { return CollectionUtils.filter( @@ -714,10 +758,15 @@ public class CompanionDeviceManagerService extends SystemService implements Bind final String appPackage = parser.getAttributeValue(null, XML_ATTR_PACKAGE); final String deviceAddress = parser.getAttributeValue(null, XML_ATTR_DEVICE); + final String profile = parser.getAttributeValue(null, XML_ATTR_PROFILE); + final boolean persistentGrants = Boolean.valueOf( + parser.getAttributeValue(null, XML_ATTR_PERSISTENT_PROFILE_GRANTS)); + if (appPackage == null || deviceAddress == null) continue; result = ArrayUtils.add(result, - new Association(userId, deviceAddress, appPackage)); + new Association(userId, deviceAddress, appPackage, + profile, persistentGrants)); } return result; } catch (XmlPullParserException | IOException e) { @@ -727,6 +776,77 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } } + void onDeviceConnected(String address) { + mCurrentlyConnectedDevices.add(address); + + Handler.getMain().removeCallbacksAndMessages(getDisconnectJobHandlerId(address)); + + for (UserInfo user : getAllUsers()) { + for (Association association : getAllAssociations(user.id)) { + if (Objects.equals(address, association.getDeviceMacAddress())) { + if (association.getDeviceProfile() != null) { + Log.i(LOG_TAG, "Granting role " + association.getDeviceProfile() + + " to " + association.getPackageName() + + " due to device connected: " + address); + mRoleManager.addRoleHolderAsUser( + association.getDeviceProfile(), + association.getPackageName(), + RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, + UserHandle.of(association.getUserId()), + getContext().getMainExecutor(), + success -> { + if (!success) { + Log.e(LOG_TAG, "Failed to grant device profile role " + + association.getDeviceProfile() + + " to " + association.getPackageName() + + " for user " + association.getUserId()); + } + }); + } + } + } + } + } + + void onDeviceDisconnected(String address) { + mCurrentlyConnectedDevices.remove(address); + + Handler.getMain().postDelayed(() -> { + if (!mCurrentlyConnectedDevices.contains(address)) { + for (UserInfo user : getAllUsers()) { + for (Association association : getAllAssociations(user.id)) { + if (association.getDeviceProfile() != null + && Objects.equals(address, association.getDeviceMacAddress()) + && !association.isKeepProfilePrivilegesWhenDeviceAway()) { + Log.i(LOG_TAG, "Revoking role " + association.getDeviceProfile() + + " to " + association.getPackageName() + + " due to device disconnected: " + address); + mRoleManager.removeRoleHolderAsUser( + association.getDeviceProfile(), + association.getPackageName(), + RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, + UserHandle.of(association.getUserId()), + getContext().getMainExecutor(), + success -> { + if (!success) { + Log.e(LOG_TAG, "Failed to revoke device profile role " + + association.getDeviceProfile() + + " to " + association.getPackageName() + + " for user " + association.getUserId()); + } + }); + } + } + } + } + }, getDisconnectJobHandlerId(address), DEVICE_DISCONNECT_PROFILE_REVOKE_DELAY_MS); + } + + @NonNull + private String getDisconnectJobHandlerId(String address) { + return "CDM_onDisconnected_" + address; + } + private class ShellCmd extends ShellCommand { public static final String USAGE = "help\n" + "list USER_ID\n" @@ -749,13 +869,22 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } break; case "associate": { - addAssociation(getNextArgInt(), getNextArgRequired(), getNextArgRequired()); + addAssociation(new Association(getNextArgInt(), getNextArgRequired(), + getNextArgRequired(), null, false)); } break; case "disassociate": { removeAssociation(getNextArgInt(), getNextArgRequired(), getNextArgRequired()); } break; + case "simulate_connect": { + onDeviceConnected(getNextArgRequired()); + } break; + + case "simulate_disconnect": { + onDeviceDisconnected(getNextArgRequired()); + } break; + default: return handleDefaultCommands(cmd); } return 0; @@ -771,4 +900,17 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } } + + private class BluetoothDeviceConnectedListener + extends BluetoothAdapter.BluetoothConnectionCallback { + @Override + public void onDeviceConnected(BluetoothDevice device) { + CompanionDeviceManagerService.this.onDeviceConnected(device.getAddress()); + } + + @Override + public void onDeviceDisconnected(BluetoothDevice device) { + CompanionDeviceManagerService.this.onDeviceDisconnected(device.getAddress()); + } + } } diff --git a/services/contentcapture/OWNERS b/services/contentcapture/OWNERS new file mode 100644 index 000000000000..a28e00a5c490 --- /dev/null +++ b/services/contentcapture/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/contentcapture/OWNERS diff --git a/services/contentsuggestions/OWNERS b/services/contentsuggestions/OWNERS new file mode 100644 index 000000000000..449db3a80b6d --- /dev/null +++ b/services/contentsuggestions/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/contentsuggestions/OWNERS diff --git a/services/core/Android.bp b/services/core/Android.bp index 17e3456e565b..252fd63ae83c 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -110,6 +110,7 @@ java_library_static { ], required: [ + "cec_config.xml", "gps_debug.conf", "protolog.conf.json.gz", ], @@ -172,6 +173,11 @@ java_library_host { } prebuilt_etc { + name: "cec_config.xml", + src: "java/com/android/server/hdmi/cec_config.xml", +} + +prebuilt_etc { name: "gps_debug.conf", src: "java/com/android/server/location/gnss/gps_debug.conf", } diff --git a/services/core/OWNERS b/services/core/OWNERS new file mode 100644 index 000000000000..88d0b61a2ab6 --- /dev/null +++ b/services/core/OWNERS @@ -0,0 +1 @@ +per-file Android.bp = file:platform/build/soong:/OWNERS diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index ee9d49244d7e..7ebe05695d5d 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -184,7 +184,6 @@ import com.android.internal.net.VpnInfo; import com.android.internal.net.VpnProfile; import com.android.internal.util.ArrayUtils; import com.android.internal.util.AsyncChannel; -import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.LocationPermissionChecker; import com.android.internal.util.MessageUtils; @@ -1287,7 +1286,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (network == null) { return null; } - return getNetworkAgentInfoForNetId(network.netId); + return getNetworkAgentInfoForNetId(network.getNetId()); } private NetworkAgentInfo getNetworkAgentInfoForNetId(int netId) { @@ -1378,7 +1377,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } final String action = blocked ? "BLOCKED" : "UNBLOCKED"; mNetworkInfoBlockingLogs.log(String.format( - "%s %d(%d) on netId %d", action, nri.mUid, nri.request.requestId, net.netId)); + "%s %d(%d) on netId %d", action, nri.mUid, nri.request.requestId, net.getNetId())); } /** @@ -1890,7 +1889,7 @@ public class ConnectivityService extends IConnectivityManager.Stub int netId; synchronized (nai) { lp = nai.linkProperties; - netId = nai.network.netId; + netId = nai.network.getNetId(); } boolean ok = addLegacyRouteToHost(lp, addr, netId, uid); if (DBG) log("requestRouteToHostAddress ok=" + ok); @@ -2525,9 +2524,21 @@ public class ConnectivityService extends IConnectivityManager.Stub PriorityDump.dump(mPriorityDumper, fd, writer, args); } + private boolean checkDumpPermission(Context context, String tag, PrintWriter pw) { + if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump " + tag + " from from pid=" + + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + + " due to missing android.permission.DUMP permission"); + return false; + } else { + return true; + } + } + private void doDump(FileDescriptor fd, PrintWriter writer, String[] args, boolean asProto) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); - if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; + if (!checkDumpPermission(mContext, TAG, pw)) return; if (asProto) return; if (ArrayUtils.contains(args, DIAG_ARG)) { @@ -2553,7 +2564,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (defaultNai == null) { pw.println("none"); } else { - pw.println(defaultNai.network.netId); + pw.println(defaultNai.network.getNetId()); } pw.println(); @@ -2690,7 +2701,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private NetworkAgentInfo[] networksSortedById() { NetworkAgentInfo[] networks = new NetworkAgentInfo[0]; networks = mNetworkAgentInfos.values().toArray(networks); - Arrays.sort(networks, Comparator.comparingInt(nai -> nai.network.netId)); + Arrays.sort(networks, Comparator.comparingInt(nai -> nai.network.getNetId())); return networks; } @@ -2831,7 +2842,7 @@ public class ConnectivityService extends IConnectivityManager.Stub log(nai.toShortString() + " changed underlying networks to " + Arrays.toString(nai.declaredUnderlyingNetworks)); } - updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities); + updateCapabilitiesForNetwork(nai); notifyIfacesChangedForNetworkStats(); } } @@ -2855,8 +2866,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (probePrivateDnsCompleted) { if (nai.networkCapabilities.isPrivateDnsBroken() != privateDnsBroken) { nai.networkCapabilities.setPrivateDnsBroken(privateDnsBroken); - final int oldScore = nai.getCurrentScore(); - updateCapabilities(oldScore, nai, nai.networkCapabilities); + updateCapabilitiesForNetwork(nai); } // Only show the notification when the private DNS is broken and the // PRIVATE_DNS_BROKEN notification hasn't shown since last valid. @@ -2871,8 +2881,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // done yet. In either case, the networkCapabilities should be updated to // reflect the new status. nai.networkCapabilities.setPrivateDnsBroken(false); - final int oldScore = nai.getCurrentScore(); - updateCapabilities(oldScore, nai, nai.networkCapabilities); + updateCapabilitiesForNetwork(nai); nai.networkAgentConfig.hasShownBroken = false; } break; @@ -2893,7 +2902,6 @@ public class ConnectivityService extends IConnectivityManager.Stub final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId); // If captive portal status has changed, update capabilities or disconnect. if (nai != null && (visible != nai.lastCaptivePortalDetected)) { - final int oldScore = nai.getCurrentScore(); nai.lastCaptivePortalDetected = visible; nai.everCaptivePortalDetected |= visible; if (nai.lastCaptivePortalDetected && @@ -2904,7 +2912,7 @@ public class ConnectivityService extends IConnectivityManager.Stub teardownUnneededNetwork(nai); break; } - updateCapabilities(oldScore, nai, nai.networkCapabilities); + updateCapabilitiesForNetwork(nai); } if (!visible) { // Only clear SIGN_IN and NETWORK_SWITCH notifications here, or else other @@ -2974,13 +2982,13 @@ public class ConnectivityService extends IConnectivityManager.Stub handleFreshlyValidatedNetwork(nai); // Clear NO_INTERNET, PRIVATE_DNS_BROKEN, PARTIAL_CONNECTIVITY and // LOST_INTERNET notifications if network becomes valid. - mNotifier.clearNotification(nai.network.netId, + mNotifier.clearNotification(nai.network.getNetId(), NotificationType.NO_INTERNET); - mNotifier.clearNotification(nai.network.netId, + mNotifier.clearNotification(nai.network.getNetId(), NotificationType.LOST_INTERNET); - mNotifier.clearNotification(nai.network.netId, + mNotifier.clearNotification(nai.network.getNetId(), NotificationType.PARTIAL_CONNECTIVITY); - mNotifier.clearNotification(nai.network.netId, + mNotifier.clearNotification(nai.network.getNetId(), NotificationType.PRIVATE_DNS_BROKEN); // If network becomes valid, the hasShownBroken should be reset for // that network so that the notification will be fired when the private @@ -2988,7 +2996,7 @@ public class ConnectivityService extends IConnectivityManager.Stub nai.networkAgentConfig.hasShownBroken = false; } } else if (partialConnectivityChanged) { - updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities); + updateCapabilitiesForNetwork(nai); } updateInetCondition(nai); // Let the NetworkAgent know the state of its network @@ -3051,7 +3059,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private final AutodestructReference<NetworkAgentInfo> mNai; private NetworkMonitorCallbacks(NetworkAgentInfo nai) { - mNetId = nai.network.netId; + mNetId = nai.network.getNetId(); mNai = new AutodestructReference<>(nai); } @@ -3201,7 +3209,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // in order to restart a validation pass from within netd. final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig(); if (cfg.useTls && TextUtils.isEmpty(cfg.hostname)) { - updateDnses(nai.linkProperties, null, nai.network.netId); + updateDnses(nai.linkProperties, null, nai.network.getNetId()); } } @@ -3234,7 +3242,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private void updatePrivateDns(NetworkAgentInfo nai, PrivateDnsConfig newCfg) { mDnsManager.updatePrivateDns(nai.network, newCfg); - updateDnses(nai.linkProperties, null, nai.network.netId); + updateDnses(nai.linkProperties, null, nai.network.getNetId()); } private void handlePrivateDnsValidationUpdate(PrivateDnsValidationUpdate update) { @@ -3330,9 +3338,9 @@ public class ConnectivityService extends IConnectivityManager.Stub if (nai != null) { final boolean wasDefault = isDefaultNetwork(nai); synchronized (mNetworkForNetId) { - mNetworkForNetId.remove(nai.network.netId); + mNetworkForNetId.remove(nai.network.getNetId()); } - mNetIdManager.releaseNetId(nai.network.netId); + mNetIdManager.releaseNetId(nai.network.getNetId()); // Just in case. mLegacyTypeTracker.remove(nai, wasDefault); } @@ -3362,7 +3370,7 @@ public class ConnectivityService extends IConnectivityManager.Stub log(nai.toShortString() + " disconnected, was satisfying " + nai.numNetworkRequests()); } // Clear all notifications of this network. - mNotifier.clearNotification(nai.network.netId); + mNotifier.clearNotification(nai.network.getNetId()); // A network agent has disconnected. // TODO - if we move the logic to the network agent (have them disconnect // because they lost all their requests or because their score isn't good) @@ -3399,14 +3407,15 @@ public class ConnectivityService extends IConnectivityManager.Stub synchronized (mNetworkForNetId) { // Remove the NetworkAgent, but don't mark the netId as // available until we've told netd to delete it below. - mNetworkForNetId.remove(nai.network.netId); + mNetworkForNetId.remove(nai.network.getNetId()); } // Remove all previously satisfied requests. for (int i = 0; i < nai.numNetworkRequests(); i++) { NetworkRequest request = nai.requestAt(i); final NetworkRequestInfo nri = mNetworkRequests.get(request); final NetworkAgentInfo currentNetwork = nri.mSatisfier; - if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) { + if (currentNetwork != null + && currentNetwork.network.getNetId() == nai.network.getNetId()) { nri.mSatisfier = null; sendUpdatedScoreToFactories(request, null); } @@ -3436,26 +3445,26 @@ public class ConnectivityService extends IConnectivityManager.Stub destroyNativeNetwork(nai); mDnsManager.removeNetwork(nai.network); } - mNetIdManager.releaseNetId(nai.network.netId); + mNetIdManager.releaseNetId(nai.network.getNetId()); } private boolean createNativeNetwork(@NonNull NetworkAgentInfo networkAgent) { try { // This should never fail. Specifying an already in use NetID will cause failure. if (networkAgent.isVPN()) { - mNetd.networkCreateVpn(networkAgent.network.netId, + mNetd.networkCreateVpn(networkAgent.network.getNetId(), (networkAgent.networkAgentConfig == null || !networkAgent.networkAgentConfig.allowBypass)); } else { - mNetd.networkCreatePhysical(networkAgent.network.netId, + mNetd.networkCreatePhysical(networkAgent.network.getNetId(), getNetworkPermission(networkAgent.networkCapabilities)); } - mDnsResolver.createNetworkCache(networkAgent.network.netId); - mDnsManager.updateTransportsForNetwork(networkAgent.network.netId, + mDnsResolver.createNetworkCache(networkAgent.network.getNetId()); + mDnsManager.updateTransportsForNetwork(networkAgent.network.getNetId(), networkAgent.networkCapabilities.getTransportTypes()); return true; } catch (RemoteException | ServiceSpecificException e) { - loge("Error creating network " + networkAgent.network.netId + ": " + loge("Error creating network " + networkAgent.network.getNetId() + ": " + e.getMessage()); return false; } @@ -3463,8 +3472,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private void destroyNativeNetwork(@NonNull NetworkAgentInfo networkAgent) { try { - mNetd.networkDestroy(networkAgent.network.netId); - mDnsResolver.destroyNetworkCache(networkAgent.network.netId); + mNetd.networkDestroy(networkAgent.network.getNetId()); + mDnsResolver.destroyNetworkCache(networkAgent.network.getNetId()); } catch (RemoteException | ServiceSpecificException e) { loge("Exception destroying network: " + e); } @@ -3656,7 +3665,7 @@ public class ConnectivityService extends IConnectivityManager.Stub nri.mSatisfier = null; if (!wasBackgroundNetwork && nai.isBackgroundNetwork()) { // Went from foreground to background. - updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities); + updateCapabilitiesForNetwork(nai); } } @@ -4026,7 +4035,7 @@ public class ConnectivityService extends IConnectivityManager.Stub Intent intent = new Intent(action); if (type != NotificationType.PRIVATE_DNS_BROKEN) { - intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.netId), null)); + intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.getNetId()), null)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // Some OEMs have their own Settings package. Thus, need to get the current using // Settings package name instead of just use default name "com.android.settings". @@ -4041,7 +4050,8 @@ public class ConnectivityService extends IConnectivityManager.Stub intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); - mNotifier.showNotification(nai.network.netId, type, nai, null, pendingIntent, highPriority); + mNotifier.showNotification( + nai.network.getNetId(), type, nai, null, pendingIntent, highPriority); } private boolean shouldPromptUnvalidated(NetworkAgentInfo nai) { @@ -4407,7 +4417,7 @@ public class ConnectivityService extends IConnectivityManager.Stub return; } if (DBG) { - int netid = nai.network.netId; + int netid = nai.network.getNetId(); log("reportNetworkConnectivity(" + netid + ", " + hasConnectivity + ") by " + uid); } // Validating a network that has not yet connected could result in a call to @@ -4442,7 +4452,7 @@ public class ConnectivityService extends IConnectivityManager.Stub return null; } return getLinkPropertiesProxyInfo(activeNetwork); - } else if (mDeps.queryUserAccess(Binder.getCallingUid(), network.netId)) { + } else if (mDeps.queryUserAccess(Binder.getCallingUid(), network.getNetId())) { // Don't call getLinkProperties() as it requires ACCESS_NETWORK_STATE permission, which // caller may not have. return getLinkPropertiesProxyInfo(network); @@ -4820,7 +4830,7 @@ public class ConnectivityService extends IConnectivityManager.Stub ensureRunningOnConnectivityServiceThread(); for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) { if (nai.supportsUnderlyingNetworks()) { - updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities); + updateCapabilitiesForNetwork(nai); } } } @@ -5653,7 +5663,7 @@ public class ConnectivityService extends IConnectivityManager.Stub return false; } synchronized (mNetworkForNetId) { - nai = mNetworkForNetId.get(network.netId); + nai = mNetworkForNetId.get(network.getNetId()); } if (nai != null) { nai.asyncChannel.sendMessage(android.net.NetworkAgent.CMD_REQUEST_BANDWIDTH_UPDATE); @@ -6033,7 +6043,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (VDBG) log("Got NetworkAgent Messenger"); mNetworkAgentInfos.put(nai.messenger, nai); synchronized (mNetworkForNetId) { - mNetworkForNetId.put(nai.network.netId, nai); + mNetworkForNetId.put(nai.network.getNetId(), nai); } try { @@ -6052,6 +6062,7 @@ public class ConnectivityService extends IConnectivityManager.Stub * Stores into |nai| any data coming from the agent that might also be written to the network's * LinkProperties by ConnectivityService itself. This ensures that the data provided by the * agent is not lost when updateLinkProperties is called. + * This method should never alter the agent's LinkProperties, only store data in |nai|. */ private void processLinkPropertiesFromAgent(NetworkAgentInfo nai, LinkProperties lp) { lp.ensureDirectlyConnectedRoutes(); @@ -6060,7 +6071,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties newLp, @NonNull LinkProperties oldLp) { - int netId = networkAgent.network.netId; + int netId = networkAgent.network.getNetId(); // The NetworkAgent does not know whether clatd is running on its network or not, or whether // a NAT64 prefix was discovered by the DNS resolver. Before we do anything else, make sure @@ -6341,7 +6352,7 @@ public class ConnectivityService extends IConnectivityManager.Stub final int newPermission = getNetworkPermission(newNc); if (oldPermission != newPermission && nai.created && !nai.isVPN()) { try { - mNetd.networkSetPermissionForNetwork(nai.network.netId, newPermission); + mNetd.networkSetPermissionForNetwork(nai.network.getNetId(), newPermission); } catch (RemoteException | ServiceSpecificException e) { loge("Exception in networkSetPermissionForNetwork: " + e); } @@ -6353,9 +6364,15 @@ public class ConnectivityService extends IConnectivityManager.Stub * Stores into |nai| any data coming from the agent that might also be written to the network's * NetworkCapabilities by ConnectivityService itself. This ensures that the data provided by the * agent is not lost when updateCapabilities is called. + * This method should never alter the agent's NetworkCapabilities, only store data in |nai|. */ private void processCapabilitiesFromAgent(NetworkAgentInfo nai, NetworkCapabilities nc) { nai.declaredMetered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED); + if (nai.networkCapabilities.getOwnerUid() != nc.getOwnerUid()) { + Log.e(TAG, nai.toShortString() + ": ignoring attempt to change owner from " + + nai.networkCapabilities.getOwnerUid() + " to " + nc.getOwnerUid()); + nc.setOwnerUid(nai.networkCapabilities.getOwnerUid()); + } } /** Modifies |caps| based on the capabilities of the specified underlying networks. */ @@ -6565,10 +6582,16 @@ public class ConnectivityService extends IConnectivityManager.Stub } if (!newNc.equalsTransportTypes(prevNc)) { - mDnsManager.updateTransportsForNetwork(nai.network.netId, newNc.getTransportTypes()); + mDnsManager.updateTransportsForNetwork( + nai.network.getNetId(), newNc.getTransportTypes()); } } + /** Convenience method to update the capabilities for a given network. */ + private void updateCapabilitiesForNetwork(NetworkAgentInfo nai) { + updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities); + } + /** * Returns whether VPN isolation (ingress interface filtering) should be applied on the given * network. @@ -6619,12 +6642,12 @@ public class ConnectivityService extends IConnectivityManager.Stub if (!newRanges.isEmpty()) { final UidRange[] addedRangesArray = new UidRange[newRanges.size()]; newRanges.toArray(addedRangesArray); - mNMS.addVpnUidRanges(nai.network.netId, addedRangesArray); + mNMS.addVpnUidRanges(nai.network.getNetId(), addedRangesArray); } if (!prevRanges.isEmpty()) { final UidRange[] removedRangesArray = new UidRange[prevRanges.size()]; prevRanges.toArray(removedRangesArray); - mNMS.removeVpnUidRanges(nai.network.netId, removedRangesArray); + mNMS.removeVpnUidRanges(nai.network.getNetId(), removedRangesArray); } final boolean wasFiltering = requiresVpnIsolation(nai, prevNc, nai.linkProperties); final boolean shouldFilter = requiresVpnIsolation(nai, newNc, nai.linkProperties); @@ -6655,7 +6678,7 @@ public class ConnectivityService extends IConnectivityManager.Stub public void handleUpdateLinkProperties(NetworkAgentInfo nai, LinkProperties newLp) { ensureRunningOnConnectivityServiceThread(); - if (getNetworkAgentInfoForNetId(nai.network.netId) != nai) { + if (getNetworkAgentInfoForNetId(nai.network.getNetId()) != nai) { // Ignore updates for disconnected networks return; } @@ -6854,8 +6877,7 @@ public class ConnectivityService extends IConnectivityManager.Stub teardownUnneededNetwork(oldNetwork); } else { // Put the network in the background. - updateCapabilities(oldNetwork.getCurrentScore(), oldNetwork, - oldNetwork.networkCapabilities); + updateCapabilitiesForNetwork(oldNetwork); } } @@ -6866,7 +6888,7 @@ public class ConnectivityService extends IConnectivityManager.Stub try { if (null != newNetwork) { - mNetd.networkSetDefault(newNetwork.network.netId); + mNetd.networkSetDefault(newNetwork.network.getNetId()); } else { mNetd.networkClearDefault(); } @@ -6929,8 +6951,8 @@ public class ConnectivityService extends IConnectivityManager.Stub public String toString() { return mRequest.mRequests.get(0).requestId + " : " - + (null != mOldNetwork ? mOldNetwork.network.netId : "null") - + " → " + (null != mNewNetwork ? mNewNetwork.network.netId : "null"); + + (null != mOldNetwork ? mOldNetwork.network.getNetId() : "null") + + " → " + (null != mNewNetwork ? mNewNetwork.network.getNetId() : "null"); } } @@ -7794,7 +7816,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private void logNetworkEvent(NetworkAgentInfo nai, int evtype) { int[] transports = nai.networkCapabilities.getTransportTypes(); - mMetricsLog.log(nai.network.netId, transports, new NetworkEvent(evtype)); + mMetricsLog.log(nai.network.getNetId(), transports, new NetworkEvent(evtype)); } private static boolean toBool(int encodedBoolean) { @@ -8416,6 +8438,6 @@ public class ConnectivityService extends IConnectivityManager.Stub KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS); } - notifyDataStallSuspected(p, network.netId); + notifyDataStallSuspected(p, network.getNetId()); } } diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java index 8ed23f900d73..c34285e9c062 100644 --- a/services/core/java/com/android/server/GestureLauncherService.java +++ b/services/core/java/com/android/server/GestureLauncherService.java @@ -257,7 +257,7 @@ public class GestureLauncherService extends SystemService { @VisibleForTesting void updateEmergencyGestureEnabled() { - boolean enabled = isEmergencyGestureEnabled(mContext, mUserId); + boolean enabled = isEmergencyGestureSettingEnabled(mContext, mUserId); synchronized (this) { mEmergencyGestureEnabled = enabled; } @@ -390,38 +390,50 @@ public class GestureLauncherService extends SystemService { /** * Whether to enable emergency gesture. */ - public static boolean isEmergencyGestureEnabled(Context context, int userId) { - return Settings.Secure.getIntForUser(context.getContentResolver(), + @VisibleForTesting + static boolean isEmergencyGestureSettingEnabled(Context context, int userId) { + return isEmergencyGestureEnabled(context.getResources()) + && Settings.Secure.getIntForUser(context.getContentResolver(), Settings.Secure.EMERGENCY_GESTURE_ENABLED, 0, userId) != 0; } /** * Whether to enable the camera launch gesture. */ - public static boolean isCameraLaunchEnabled(Resources resources) { + private static boolean isCameraLaunchEnabled(Resources resources) { boolean configSet = resources.getInteger( com.android.internal.R.integer.config_cameraLaunchGestureSensorType) != -1; return configSet && !SystemProperties.getBoolean("gesture.disable_camera_launch", false); } - public static boolean isCameraDoubleTapPowerEnabled(Resources resources) { + @VisibleForTesting + static boolean isCameraDoubleTapPowerEnabled(Resources resources) { return resources.getBoolean( com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled); } - public static boolean isCameraLiftTriggerEnabled(Resources resources) { + private static boolean isCameraLiftTriggerEnabled(Resources resources) { boolean configSet = resources.getInteger( com.android.internal.R.integer.config_cameraLiftTriggerSensorType) != -1; return configSet; } /** + * Whether or not the emergency gesture feature is enabled by platform + */ + private static boolean isEmergencyGestureEnabled(Resources resources) { + return resources.getBoolean(com.android.internal.R.bool.config_emergencyGestureEnabled); + } + + /** * Whether GestureLauncherService should be enabled according to system properties. */ public static boolean isGestureLauncherEnabled(Resources resources) { - return isCameraLaunchEnabled(resources) || isCameraDoubleTapPowerEnabled(resources) || - isCameraLiftTriggerEnabled(resources); + return isCameraLaunchEnabled(resources) + || isCameraDoubleTapPowerEnabled(resources) + || isCameraLiftTriggerEnabled(resources) + || isEmergencyGestureEnabled(resources); } /** diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index b2f0c8376db1..f648c3e146de 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -31,6 +31,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.net.IIpSecService; import android.net.INetd; +import android.net.InetAddresses; import android.net.IpSecAlgorithm; import android.net.IpSecConfig; import android.net.IpSecManager; @@ -41,7 +42,6 @@ import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecUdpEncapResponse; import android.net.LinkAddress; import android.net.Network; -import android.net.NetworkUtils; import android.net.TrafficStats; import android.net.util.NetdService; import android.os.Binder; @@ -1083,7 +1083,7 @@ public class IpSecService extends IIpSecService.Stub { throw new IllegalArgumentException("Unspecified address"); } - InetAddress checkAddr = NetworkUtils.numericToInetAddress(inetAddress); + InetAddress checkAddr = InetAddresses.parseNumericAddress(inetAddress); if (checkAddr.isAnyLocalAddress()) { throw new IllegalArgumentException("Inappropriate wildcard address: " + inetAddress); @@ -1467,7 +1467,7 @@ public class IpSecService extends IIpSecService.Stub { private int getFamily(String inetAddress) { int family = AF_UNSPEC; - InetAddress checkAddress = NetworkUtils.numericToInetAddress(inetAddress); + InetAddress checkAddress = InetAddresses.parseNumericAddress(inetAddress); if (checkAddress instanceof Inet4Address) { family = AF_INET; } else if (checkAddress instanceof Inet6Address) { diff --git a/services/core/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java index 793e34292623..e248b215ef4a 100644 --- a/services/core/java/com/android/server/MasterClearReceiver.java +++ b/services/core/java/com/android/server/MasterClearReceiver.java @@ -25,7 +25,6 @@ import android.os.RecoverySystem; import android.os.UserHandle; import android.os.storage.StorageManager; import android.text.TextUtils; -import android.util.Log; import android.util.Slog; import android.view.WindowManager; @@ -59,6 +58,7 @@ public class MasterClearReceiver extends BroadcastReceiver { .getString(com.android.internal.R.string.config_factoryResetPackage); if (Intent.ACTION_FACTORY_RESET.equals(intent.getAction()) && !TextUtils.isEmpty(factoryResetPackage)) { + Slog.i(TAG, "Re-directing intent to " + factoryResetPackage); intent.setPackage(factoryResetPackage).setComponent(null); context.sendBroadcastAsUser(intent, UserHandle.SYSTEM); return; @@ -77,9 +77,12 @@ public class MasterClearReceiver extends BroadcastReceiver { @Override public void run() { try { + Slog.i(TAG, "Calling RecoverySystem.rebootWipeUserData(context, " + + "shutdown=" + shutdown + ", reason=" + reason + + ", forceWipe=" + forceWipe + ", wipeEsims=" + mWipeEsims + ")"); RecoverySystem .rebootWipeUserData(context, shutdown, reason, forceWipe, mWipeEsims); - Log.wtf(TAG, "Still running after master clear?!"); + Slog.wtf(TAG, "Still running after master clear?!"); } catch (IOException e) { Slog.e(TAG, "Can't perform master clear/factory reset", e); } catch (SecurityException e) { @@ -90,8 +93,10 @@ public class MasterClearReceiver extends BroadcastReceiver { if (mWipeExternalStorage) { // thr will be started at the end of this task. + Slog.i(TAG, "Wiping external storage on async task"); new WipeDataTask(context, thr).execute(); } else { + Slog.i(TAG, "NOT wiping external storage; starting thread " + thr.getName()); thr.start(); } } diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 821a967b2b3d..5e86f855c1e7 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -58,7 +58,6 @@ import android.net.Network; import android.net.NetworkPolicyManager; import android.net.NetworkStack; import android.net.NetworkStats; -import android.net.NetworkUtils; import android.net.RouteInfo; import android.net.TetherStatsParcel; import android.net.UidRange; @@ -803,7 +802,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub { InterfaceConfiguration cfg = new InterfaceConfiguration(); cfg.setHardwareAddress(p.hwAddr); - final InetAddress addr = NetworkUtils.numericToInetAddress(p.ipv4Addr); + final InetAddress addr = InetAddresses.parseNumericAddress(p.ipv4Addr); cfg.setLinkAddress(new LinkAddress(addr, p.prefixLength)); for (String flag : p.flags) { cfg.setFlag(flag); diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS index 8706cdf41df9..733590c4f6c6 100644 --- a/services/core/java/com/android/server/OWNERS +++ b/services/core/java/com/android/server/OWNERS @@ -9,3 +9,21 @@ per-file ZramWriteback.java = minchan@google.com, rajekumar@google.com, srnvs@go # Userspace reboot per-file UserspaceRebootLogger.java = ioffe@google.com, tomcherry@google.com + +per-file *Alarm* = file:/apex/jobscheduler/OWNERS +per-file *AppOps* = file:/core/java/android/permission/OWNERS +per-file *Bluetooth* = file:/core/java/android/bluetooth/OWNERS +per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS +per-file *Location* = file:/services/core/java/com/android/server/location/OWNERS +per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS +per-file *Storage* = file:/core/java/android/os/storage/OWNERS +per-file *TimeUpdate* = file:/core/java/android/app/timezone/OWNERS +per-file ConnectivityService.java = file:/services/core/java/com/android/server/net/OWNERS +per-file GestureLauncherService.java = file:platform/packages/apps/EmergencyInfo:/OWNERS +per-file IpSecService.java = file:/services/core/java/com/android/server/net/OWNERS +per-file MmsServiceBroker.java = file:/telephony/OWNERS +per-file NetIdManager.java = file:/services/core/java/com/android/server/net/OWNERS +per-file PackageWatchdog.java = file:/services/core/java/com/android/server/rollback/OWNERS +per-file TelephonyRegistry.java = file:/telephony/OWNERS +per-file UiModeManagerService.java = file:/packages/SystemUI/OWNERS +per-file VcnManagementService.java = file:/services/core/java/com/android/server/vcn/OWNERS diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index dbd27af49b17..c95bfd031af4 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -108,7 +108,6 @@ import android.os.storage.StorageManagerInternal; import android.os.storage.StorageVolume; import android.os.storage.VolumeInfo; import android.os.storage.VolumeRecord; -import android.provider.DeviceConfig; import android.provider.DocumentsContract; import android.provider.Downloads; import android.provider.MediaStore; @@ -206,27 +205,6 @@ class StorageManagerService extends IStorageManager.Stub private static final String ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY = "persist.sys.vold_app_data_isolation_enabled"; - // TODO(b/169327180): Will be fetched from the server, but for now, we emulate this in - // the system_server since it can write to DeviceConfig and MediaProvider can read it - private static final String PROP_TRANSCODE_ENABLED = "transcode_enabled"; - private static final String PROP_TRANSCODE_DEFAULT = "transcode_default"; - private static final String PROP_TRANSCODE_COMPAT_MANIFEST = "transcode_compat_manifest"; - private static final boolean TRANSCODE_ENABLED_VALUE = false; - // Determines the default behavior of apps when transcode is enabled, AKA, Option A/Option B. - // If true, transcode by default (Option B). If false, don't transcode by default (Option A) - // For dogfood, we go with Option B - private static final boolean TRANSCODE_DEFAULT_VALUE = true; - // Format is <package_name>,<media_capability_bit_mask>,... - // media_capability_bit_mask is defined in MediaProvider/../TranscodeHelper.java: - // FLAG_HEVC = 1 << 0; - // FLAG_SLOW_MOTION = 1 << 1; - // FLAG_HDR_10 = 1 << 2; - // FLAG_HDR_10_PLUS = 1 << 3; - // FLAG_HDR_HLG = 1 << 4; - // FLAG_HDR_DOLBY_VISION = 1 << 5; - private static final String TRANSCODE_COMPAT_MANIFEST_VALUE = - "com.google.android.apps.photos,1"; - // How long we wait to reset storage, if we failed to call onMount on the // external storage service. public static final int FAILED_MOUNT_RESET_TIMEOUT_SECONDS = 10; @@ -901,18 +879,6 @@ class StorageManagerService extends IStorageManager.Stub com.android.internal.R.bool.config_zramWriteback)) { ZramWriteback.scheduleZramWriteback(mContext); } - - // TODO(b/169327180): Remove after setting up server-side DeviceConfig flags - // Set DeviceConfig values for transcoding that will be read by MediaProvider - DeviceConfig.setProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, - PROP_TRANSCODE_ENABLED, String.valueOf(TRANSCODE_ENABLED_VALUE), - false /* makeDefault */); - DeviceConfig.setProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, - PROP_TRANSCODE_DEFAULT, String.valueOf(TRANSCODE_DEFAULT_VALUE), - false /* makeDefault */); - DeviceConfig.setProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, - PROP_TRANSCODE_COMPAT_MANIFEST, TRANSCODE_COMPAT_MANIFEST_VALUE, - false /* makeDefault */); } /** diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java index 9d60b8438153..cb6e73af56ac 100644 --- a/services/core/java/com/android/server/SystemServiceManager.java +++ b/services/core/java/com/android/server/SystemServiceManager.java @@ -60,12 +60,12 @@ public final class SystemServiceManager implements Dumpable { // Constants used on onUser(...) // NOTE: do not change their values, as they're used on Trace calls and changes might break // performance tests that rely on them. - private static final String USER_STARTING = "Start"; - private static final String USER_UNLOCKING = "Unlocking"; - private static final String USER_UNLOCKED = "Unlocked"; - private static final String USER_SWITCHING = "Switch"; - private static final String USER_STOPPING = "Stop"; - private static final String USER_STOPPED = "Cleanup"; + private static final String USER_STARTING = "Start"; // Logged as onStartUser + private static final String USER_UNLOCKING = "Unlocking"; // Logged as onUnlockingUser + private static final String USER_UNLOCKED = "Unlocked"; // Logged as onUnlockedUser + private static final String USER_SWITCHING = "Switch"; // Logged as onSwitchUser + private static final String USER_STOPPING = "Stop"; // Logged as onStopUser + private static final String USER_STOPPED = "Cleanup"; // Logged as onCleanupUser private static File sSystemDir; private final Context mContext; diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 52eb77d7d47d..ae5c131e38ab 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -2361,6 +2361,40 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } + /** + * Notify that the data enabled has changed. + * + * @param enabled True if data is enabled, otherwise disabled. + * @param reason Reason for data enabled/disabled. See {@code DATA_*} in + * {@link TelephonyManager}. + */ + public void notifyDataEnabled(boolean enabled, + @TelephonyManager.DataEnabledReason int reason) { + if (!checkNotifyPermission("notifyDataEnabled()")) { + return; + } + + if (VDBG) { + log("notifyDataEnabled: enabled=" + enabled + " reason=" + reason); + } + + mIsDataEnabled = enabled; + mDataEnabledReason = reason; + synchronized (mRecords) { + for (Record r : mRecords) { + if (r.matchPhoneStateListenerEvent( + PhoneStateListener.EVENT_DATA_ENABLED_CHANGED)) { + try { + r.callback.onDataEnabledChanged(enabled, reason); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + } + @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); @@ -2413,6 +2447,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println("mDefaultPhoneId=" + mDefaultPhoneId); pw.println("mDefaultSubId=" + mDefaultSubId); pw.println("mPhysicalChannelConfigs=" + mPhysicalChannelConfigs); + pw.println("mIsDataEnabled=" + mIsDataEnabled); + pw.println("mDataEnabledReason=" + mDataEnabledReason); pw.decreaseIndent(); diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java index a45466d98563..75ebe70591df 100644 --- a/services/core/java/com/android/server/TestNetworkService.java +++ b/services/core/java/com/android/server/TestNetworkService.java @@ -220,7 +220,7 @@ class TestNetworkService extends ITestNetworkManager.Stub { // Has to be in TestNetworkAgent to ensure all teardown codepaths properly clean up // resources, even for binder death or unwanted calls. synchronized (mTestNetworkTracker) { - mTestNetworkTracker.remove(getNetwork().netId); + mTestNetworkTracker.remove(getNetwork().getNetId()); } } } @@ -339,7 +339,7 @@ class TestNetworkService extends ITestNetworkManager.Stub { administratorUids, binder); - mTestNetworkTracker.put(agent.getNetwork().netId, agent); + mTestNetworkTracker.put(agent.getNetwork().getNetId(), agent); } } catch (SocketException e) { throw new UncheckedIOException(e); diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java index f49f1b15c93a..7f638b9a55a2 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -1737,9 +1737,12 @@ final class UiModeManagerService extends SystemService { context.getString(R.string.car_mode_disable_notification_title)) .setContentText( context.getString(R.string.car_mode_disable_notification_message)) + .setContentIntent( + // TODO(b/173744200) Please replace FLAG_MUTABLE_UNAUDITED below + // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent.getActivityAsUser(context, 0, - carModeOffIntent, 0, + carModeOffIntent, PendingIntent.FLAG_MUTABLE_UNAUDITED, null, UserHandle.CURRENT)); mNotificationManager.notifyAsUser(null, SystemMessage.NOTE_CAR_MODE_DISABLE, n.build(), UserHandle.ALL); diff --git a/services/core/java/com/android/server/VibratorManagerService.java b/services/core/java/com/android/server/VibratorManagerService.java index f1f2815be8fa..eca1dfaed810 100644 --- a/services/core/java/com/android/server/VibratorManagerService.java +++ b/services/core/java/com/android/server/VibratorManagerService.java @@ -16,32 +16,85 @@ package com.android.server; +import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.AppOpsManager; import android.content.Context; +import android.content.pm.PackageManager; +import android.hardware.vibrator.IVibrator; import android.os.CombinedVibrationEffect; +import android.os.Handler; import android.os.IBinder; import android.os.IVibratorManagerService; +import android.os.Looper; import android.os.ResultReceiver; import android.os.ShellCallback; import android.os.ShellCommand; +import android.os.Trace; import android.os.VibrationAttributes; +import android.os.VibrationEffect; +import android.os.Vibrator; +import android.os.VibratorInfo; +import android.util.Slog; +import android.util.SparseArray; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.vibrator.Vibration; +import com.android.server.vibrator.VibrationScaler; +import com.android.server.vibrator.VibrationSettings; +import com.android.server.vibrator.VibratorController; import libcore.util.NativeAllocationRegistry; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.lang.ref.WeakReference; import java.util.Arrays; +import java.util.function.Consumer; +import java.util.function.Function; /** System implementation of {@link IVibratorManagerService}. */ public class VibratorManagerService extends IVibratorManagerService.Stub { private static final String TAG = "VibratorManagerService"; private static final boolean DEBUG = false; + private static final VibrationAttributes DEFAULT_ATTRIBUTES = + new VibrationAttributes.Builder().build(); + /** Lifecycle responsible for initializing this class at the right system server phases. */ + public static class Lifecycle extends SystemService { + private VibratorManagerService mService; + + public Lifecycle(Context context) { + super(context); + } + + @Override + public void onStart() { + mService = new VibratorManagerService(getContext(), new Injector()); + publishBinderService("vibrator_manager", mService); + } + + @Override + public void onBootPhase(int phase) { + if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { + mService.systemReady(); + } + } + } + + private final Object mLock = new Object(); private final Context mContext; + private final Handler mHandler; + private final AppOpsManager mAppOps; private final NativeWrapper mNativeWrapper; private final int[] mVibratorIds; + private final SparseArray<VibratorController> mVibrators; + @GuardedBy("mLock") + private final SparseArray<AlwaysOnVibration> mAlwaysOnEffects = new SparseArray<>(); + + private VibrationSettings mVibrationSettings; + private VibrationScaler mVibrationScaler; static native long nativeInit(); @@ -49,19 +102,53 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { static native int[] nativeGetVibratorIds(long nativeServicePtr); - VibratorManagerService(Context context) { - this(context, new Injector()); - } - @VisibleForTesting VibratorManagerService(Context context, Injector injector) { mContext = context; + mHandler = injector.createHandler(Looper.myLooper()); mNativeWrapper = injector.getNativeWrapper(); - mNativeWrapper.init(); + mAppOps = mContext.getSystemService(AppOpsManager.class); + int[] vibratorIds = mNativeWrapper.getVibratorIds(); - mVibratorIds = vibratorIds == null ? new int[0] : vibratorIds; + if (vibratorIds == null) { + mVibratorIds = new int[0]; + mVibrators = new SparseArray<>(0); + } else { + // Keep original vibrator id order, which might be meaningful. + mVibratorIds = vibratorIds; + mVibrators = new SparseArray<>(mVibratorIds.length); + VibrationCompleteListener listener = new VibrationCompleteListener(this); + for (int vibratorId : vibratorIds) { + mVibrators.put(vibratorId, injector.createVibratorController(vibratorId, listener)); + } + } + } + + /** Finish initialization at boot phase {@link SystemService#PHASE_SYSTEM_SERVICES_READY}. */ + @VisibleForTesting + void systemReady() { + Slog.v(TAG, "Initializing VibratorManager service..."); + Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "systemReady"); + try { + mVibrationSettings = new VibrationSettings(mContext, mHandler); + mVibrationScaler = new VibrationScaler(mContext, mVibrationSettings); + + mVibrationSettings.addListener(this::updateServiceState); + + updateServiceState(); + } finally { + Slog.v(TAG, "VibratorManager service initialized"); + Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); + } + } + + @Override // Binder call + @Nullable + public VibratorInfo getVibratorInfo(int vibratorId) { + VibratorController controller = mVibrators.get(vibratorId); + return controller == null ? null : controller.getVibratorInfo(); } @Override // Binder call @@ -70,7 +157,48 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } @Override // Binder call - public void vibrate(int uid, String opPkg, CombinedVibrationEffect effect, + public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, + @Nullable CombinedVibrationEffect effect, @Nullable VibrationAttributes attrs) { + Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "setAlwaysOnEffect"); + try { + if (!hasPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)) { + throw new SecurityException("Requires VIBRATE_ALWAYS_ON permission"); + } + if (effect == null) { + synchronized (mLock) { + mAlwaysOnEffects.delete(alwaysOnId); + onAllVibratorsLocked(v -> { + if (v.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { + v.updateAlwaysOn(alwaysOnId, /* effect= */ null); + } + }); + } + return true; + } + if (!isEffectValid(effect)) { + return false; + } + attrs = fixupVibrationAttributes(attrs); + synchronized (mLock) { + SparseArray<VibrationEffect.Prebaked> effects = fixupAlwaysOnEffectsLocked(effect); + if (effects == null) { + // Invalid effects set in CombinedVibrationEffect, or always-on capability is + // missing on individual vibrators. + return false; + } + AlwaysOnVibration alwaysOnVibration = new AlwaysOnVibration( + alwaysOnId, uid, opPkg, attrs, effects); + mAlwaysOnEffects.put(alwaysOnId, alwaysOnVibration); + updateAlwaysOnLocked(alwaysOnVibration); + } + return true; + } finally { + Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); + } + } + + @Override // Binder call + public void vibrate(int uid, String opPkg, @NonNull CombinedVibrationEffect effect, @Nullable VibrationAttributes attrs, String reason, IBinder token) { throw new UnsupportedOperationException("Not implemented"); } @@ -86,6 +214,201 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { new VibratorManagerShellCommand(this).exec(this, in, out, err, args, cb, resultReceiver); } + private void updateServiceState() { + synchronized (mLock) { + for (int i = 0; i < mAlwaysOnEffects.size(); i++) { + updateAlwaysOnLocked(mAlwaysOnEffects.valueAt(i)); + } + } + } + + @GuardedBy("mLock") + private void updateAlwaysOnLocked(AlwaysOnVibration vib) { + for (int i = 0; i < vib.effects.size(); i++) { + VibratorController vibrator = mVibrators.get(vib.effects.keyAt(i)); + VibrationEffect.Prebaked effect = vib.effects.valueAt(i); + if (vibrator == null) { + continue; + } + Vibration.Status ignoredStatus = shouldIgnoreVibrationLocked( + vib.uid, vib.opPkg, vib.attrs); + if (ignoredStatus == null) { + effect = mVibrationScaler.scale(effect, vib.attrs.getUsage()); + } else { + // Vibration should not run, use null effect to remove registered effect. + effect = null; + } + vibrator.updateAlwaysOn(vib.alwaysOnId, effect); + } + } + + /** + * Check if a vibration with given {@code uid}, {@code opPkg} and {@code attrs} should be + * ignored by this service. + * + * @param uid The user id of this vibration + * @param opPkg The package name of this vibration + * @param attrs The attributes of this vibration + * @return One of Vibration.Status.IGNORED_* values if the vibration should be ignored. + */ + @GuardedBy("mLock") + @Nullable + private Vibration.Status shouldIgnoreVibrationLocked(int uid, String opPkg, + VibrationAttributes attrs) { + if (!mVibrationSettings.shouldVibrateForPowerMode(attrs.getUsage())) { + return Vibration.Status.IGNORED_FOR_POWER; + } + + int intensity = mVibrationSettings.getCurrentIntensity(attrs.getUsage()); + if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) { + return Vibration.Status.IGNORED_FOR_SETTINGS; + } + + if (!mVibrationSettings.shouldVibrateForRingerMode(attrs.getUsage())) { + if (DEBUG) { + Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones"); + } + return Vibration.Status.IGNORED_RINGTONE; + } + + int mode = getAppOpMode(uid, opPkg, attrs); + if (mode != AppOpsManager.MODE_ALLOWED) { + if (mode == AppOpsManager.MODE_ERRORED) { + // We might be getting calls from within system_server, so we don't actually + // want to throw a SecurityException here. + Slog.w(TAG, "Would be an error: vibrate from uid " + uid); + return Vibration.Status.IGNORED_ERROR_APP_OPS; + } else { + return Vibration.Status.IGNORED_APP_OPS; + } + } + + return null; + } + + /** + * Check which mode should be set for a vibration with given {@code uid}, {@code opPkg} and + * {@code attrs}. This will return one of the AppOpsManager.MODE_*. + */ + private int getAppOpMode(int uid, String opPkg, VibrationAttributes attrs) { + int mode = mAppOps.checkAudioOpNoThrow(AppOpsManager.OP_VIBRATE, + attrs.getAudioUsage(), uid, opPkg); + if (mode == AppOpsManager.MODE_ALLOWED) { + mode = mAppOps.startOpNoThrow(AppOpsManager.OP_VIBRATE, uid, opPkg); + } + if (mode == AppOpsManager.MODE_IGNORED + && attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY)) { + // If we're just ignoring the vibration op then this is set by DND and we should ignore + // if we're asked to bypass. AppOps won't be able to record this operation, so make + // sure we at least note it in the logs for debugging. + Slog.d(TAG, "Bypassing DND for vibrate from uid " + uid); + mode = AppOpsManager.MODE_ALLOWED; + } + return mode; + } + + /** + * Validate the incoming {@link CombinedVibrationEffect}. + * + * We can't throw exceptions here since we might be called from some system_server component, + * which would bring the whole system down. + * + * @return whether the CombinedVibrationEffect is non-null and valid + */ + private static boolean isEffectValid(@Nullable CombinedVibrationEffect effect) { + if (effect == null) { + Slog.wtf(TAG, "effect must not be null"); + return false; + } + try { + effect.validate(); + } catch (Exception e) { + Slog.wtf(TAG, "Encountered issue when verifying CombinedVibrationEffect.", e); + return false; + } + return true; + } + + /** + * Return new {@link VibrationAttributes} that only applies flags that this user has permissions + * to use. + */ + private VibrationAttributes fixupVibrationAttributes(@Nullable VibrationAttributes attrs) { + if (attrs == null) { + attrs = DEFAULT_ATTRIBUTES; + } + if (attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY)) { + if (!(hasPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + || hasPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + || hasPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING))) { + final int flags = attrs.getFlags() + & ~VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY; + attrs = new VibrationAttributes.Builder(attrs) + .setFlags(flags, attrs.getFlags()).build(); + } + } + return attrs; + } + + @GuardedBy("mLock") + @Nullable + private SparseArray<VibrationEffect.Prebaked> fixupAlwaysOnEffectsLocked( + CombinedVibrationEffect effect) { + Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "fixupAlwaysOnEffectsLocked"); + try { + SparseArray<VibrationEffect> effects; + if (effect instanceof CombinedVibrationEffect.Mono) { + VibrationEffect syncedEffect = ((CombinedVibrationEffect.Mono) effect).getEffect(); + effects = transformAllVibratorsLocked(unused -> syncedEffect); + } else if (effect instanceof CombinedVibrationEffect.Stereo) { + effects = ((CombinedVibrationEffect.Stereo) effect).getEffects(); + } else { + // Only synced combinations can be used for always-on effects. + return null; + } + SparseArray<VibrationEffect.Prebaked> result = new SparseArray<>(); + for (int i = 0; i < effects.size(); i++) { + VibrationEffect prebaked = effects.valueAt(i); + if (!(prebaked instanceof VibrationEffect.Prebaked)) { + Slog.e(TAG, "Only prebaked effects supported for always-on."); + return null; + } + int vibratorId = effects.keyAt(i); + VibratorController vibrator = mVibrators.get(vibratorId); + if (vibrator != null && vibrator.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { + result.put(vibratorId, (VibrationEffect.Prebaked) prebaked); + } + } + if (result.size() == 0) { + return null; + } + return result; + } finally { + Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); + } + } + + private boolean hasPermission(String permission) { + return mContext.checkCallingOrSelfPermission(permission) + == PackageManager.PERMISSION_GRANTED; + } + + @GuardedBy("mLock") + private void onAllVibratorsLocked(Consumer<VibratorController> consumer) { + for (int i = 0; i < mVibrators.size(); i++) { + consumer.accept(mVibrators.valueAt(i)); + } + } + + @GuardedBy("mLock") + private <T> SparseArray<T> transformAllVibratorsLocked(Function<VibratorController, T> fn) { + SparseArray<T> ret = new SparseArray<>(mVibrators.size()); + for (int i = 0; i < mVibrators.size(); i++) { + ret.put(mVibrators.keyAt(i), fn.apply(mVibrators.valueAt(i))); + } + return ret; + } + /** Point of injection for test dependencies */ @VisibleForTesting static class Injector { @@ -93,6 +416,57 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { NativeWrapper getNativeWrapper() { return new NativeWrapper(); } + + Handler createHandler(Looper looper) { + return new Handler(looper); + } + + VibratorController createVibratorController(int vibratorId, + VibratorController.OnVibrationCompleteListener listener) { + return new VibratorController(vibratorId, listener); + } + } + + /** + * Implementation of {@link VibratorController.OnVibrationCompleteListener} with a weak + * reference to this service. + */ + private static final class VibrationCompleteListener implements + VibratorController.OnVibrationCompleteListener { + private WeakReference<VibratorManagerService> mServiceRef; + + VibrationCompleteListener(VibratorManagerService service) { + mServiceRef = new WeakReference<>(service); + } + + @Override + public void onComplete(int vibratorId, long vibrationId) { + VibratorManagerService service = mServiceRef.get(); + if (service != null) { + // TODO(b/159207608): finish vibration if all vibrators finished for this vibration + } + } + } + + /** + * Combination of prekabed vibrations on multiple vibrators, with the same {@link + * VibrationAttributes}, that can be set for always-on effects. + */ + private static final class AlwaysOnVibration { + public final int alwaysOnId; + public final int uid; + public final String opPkg; + public final VibrationAttributes attrs; + public final SparseArray<VibrationEffect.Prebaked> effects; + + AlwaysOnVibration(int alwaysOnId, int uid, String opPkg, VibrationAttributes attrs, + SparseArray<VibrationEffect.Prebaked> effects) { + this.alwaysOnId = alwaysOnId; + this.uid = uid; + this.opPkg = opPkg; + this.attrs = attrs; + this.effects = effects; + } } /** Wrapper around the static-native methods of {@link VibratorManagerService} for tests. */ @@ -120,7 +494,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } } - /** Provides limited functionality from {@link VibratorManagerService} as shell commands. */ + /** Provide limited functionality from {@link VibratorManagerService} as shell commands. */ private final class VibratorManagerShellCommand extends ShellCommand { private final IBinder mToken; diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java index db2b4e4edd2b..6a9715e49b99 100644 --- a/services/core/java/com/android/server/VibratorService.java +++ b/services/core/java/com/android/server/VibratorService.java @@ -19,7 +19,6 @@ package com.android.server; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.AppOpsManager; -import android.app.IUidObserver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -37,9 +36,6 @@ import android.os.IVibratorService; import android.os.IVibratorStateListener; import android.os.Looper; import android.os.PowerManager; -import android.os.PowerManager.ServiceType; -import android.os.PowerManagerInternal; -import android.os.PowerSaveState; import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; @@ -51,9 +47,9 @@ import android.os.Trace; import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.Vibrator; +import android.os.VibratorInfo; import android.os.WorkSource; import android.util.Slog; -import android.util.SparseArray; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; @@ -73,7 +69,6 @@ import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.LinkedList; -import java.util.List; import java.util.concurrent.atomic.AtomicInteger; /** System implementation of {@link IVibratorService}. */ @@ -95,7 +90,6 @@ public class VibratorService extends IVibratorService.Stub { private final LinkedList<Vibration.DebugInfo> mPreviousExternalVibrations; private final LinkedList<Vibration.DebugInfo> mPreviousVibrations; private final int mPreviousVibrationsLimit; - private final SparseArray<Integer> mProcStatesCache = new SparseArray<>(); private final WorkSource mTmpWorkSource = new WorkSource(); private final Handler mH; private final Object mLock = new Object(); @@ -106,7 +100,6 @@ public class VibratorService extends IVibratorService.Stub { private final AppOpsManager mAppOps; private final IBatteryStats mBatteryStatsService; private final String mSystemUiPackage; - private PowerManagerInternal mPowerManagerInternal; private VibrationSettings mVibrationSettings; private VibrationScaler mVibrationScaler; private InputDeviceDelegate mInputDeviceDelegate; @@ -119,31 +112,6 @@ public class VibratorService extends IVibratorService.Stub { private VibrationDeathRecipient mCurrentVibrationDeathRecipient; private int mCurVibUid = -1; private ExternalVibrationHolder mCurrentExternalVibration; - private boolean mLowPowerMode; - private SparseArray<Vibration> mAlwaysOnEffects = new SparseArray<>(); - - private final IUidObserver mUidObserver = new IUidObserver.Stub() { - @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, - int capability) { - mProcStatesCache.put(uid, procState); - } - - @Override public void onUidGone(int uid, boolean disabled) { - mProcStatesCache.delete(uid); - } - - @Override - public void onUidActive(int uid) { - } - - @Override - public void onUidIdle(int uid, boolean disabled) { - } - - @Override - public void onUidCachedChanged(int uid, boolean cached) { - } - }; /** * Implementation of {@link OnVibrationCompleteListener} with a weak reference to this service. @@ -277,37 +245,15 @@ public class VibratorService extends IVibratorService.Stub { mVibrationScaler = new VibrationScaler(mContext, mVibrationSettings); mInputDeviceDelegate = new InputDeviceDelegate(mContext, mH); - mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); - mPowerManagerInternal.registerLowPowerModeObserver( - new PowerManagerInternal.LowPowerModeListener() { - @Override - public int getServiceType() { - return ServiceType.VIBRATION; - } - - @Override - public void onLowPowerModeChanged(PowerSaveState result) { - updateVibrators(); - } - }); - mVibrationSettings.addListener(this::updateVibrators); mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - updateVibrators(); + mVibrationSettings.updateSettings(); } }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH); - try { - ActivityManager.getService().registerUidObserver(mUidObserver, - ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE, - ActivityManager.PROCESS_STATE_UNKNOWN, null); - } catch (RemoteException e) { - // ignored; both services live in system_server - } - updateVibrators(); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); @@ -346,6 +292,11 @@ public class VibratorService extends IVibratorService.Stub { } @Override // Binder call + public VibratorInfo getVibratorInfo() { + return mVibratorController.getVibratorInfo(); + } + + @Override // Binder call public boolean registerVibratorStateListener(IVibratorStateListener listener) { if (!hasPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)) { throw new SecurityException("Requires ACCESS_VIBRATOR_STATE permission"); @@ -369,61 +320,6 @@ public class VibratorService extends IVibratorService.Stub { || mVibratorController.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL); } - @Override // Binder call - public int[] areEffectsSupported(int[] effectIds) { - return mVibratorController.areEffectsSupported(effectIds); - } - - @Override // Binder call - public boolean[] arePrimitivesSupported(int[] primitiveIds) { - return mVibratorController.arePrimitivesSupported(primitiveIds); - } - - private static List<Integer> asList(int... vals) { - if (vals == null) { - return null; - } - List<Integer> l = new ArrayList<>(vals.length); - for (int val : vals) { - l.add(val); - } - return l; - } - - @Override // Binder call - public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, VibrationEffect effect, - VibrationAttributes attrs) { - if (!hasPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)) { - throw new SecurityException("Requires VIBRATE_ALWAYS_ON permission"); - } - if (!mVibratorController.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { - Slog.e(TAG, "Always-on effects not supported."); - return false; - } - if (effect == null) { - synchronized (mLock) { - mAlwaysOnEffects.delete(alwaysOnId); - mVibratorController.updateAlwaysOn(alwaysOnId, /* effect= */ null); - } - } else { - if (!verifyVibrationEffect(effect)) { - return false; - } - if (!(effect instanceof VibrationEffect.Prebaked)) { - Slog.e(TAG, "Only prebaked effects supported for always-on."); - return false; - } - attrs = fixupVibrationAttributes(attrs); - synchronized (mLock) { - Vibration vib = new Vibration(null, mNextVibrationId.getAndIncrement(), effect, - attrs, uid, opPkg, null); - mAlwaysOnEffects.put(alwaysOnId, vib); - updateAlwaysOnLocked(alwaysOnId, vib); - } - } - return true; - } - private void verifyIncomingUid(int uid) { if (uid == Binder.getCallingUid()) { return; @@ -543,9 +439,7 @@ public class VibratorService extends IVibratorService.Stub { return; } - if (mProcStatesCache.get(uid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) - > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND - && !isNotification(vib) && !isRingtone(vib) && !isAlarm(vib)) { + if (!mVibrationSettings.shouldVibrateForUid(uid, vib.attrs.getUsage())) { Slog.e(TAG, "Ignoring incoming vibration as process with" + " uid= " + uid + " is background," + " attrs= " + vib.attrs); @@ -582,16 +476,19 @@ public class VibratorService extends IVibratorService.Stub { private void endVibrationLocked(Vibration vib, Vibration.Status status) { final LinkedList<Vibration.DebugInfo> previousVibrations; - if (isRingtone(vib)) { - previousVibrations = mPreviousRingVibrations; - } else if (isNotification(vib)) { - previousVibrations = mPreviousNotificationVibrations; - } else if (isAlarm(vib)) { - previousVibrations = mPreviousAlarmVibrations; - } else { - previousVibrations = mPreviousVibrations; + switch (vib.attrs.getUsage()) { + case VibrationAttributes.USAGE_NOTIFICATION: + previousVibrations = mPreviousNotificationVibrations; + break; + case VibrationAttributes.USAGE_RINGTONE: + previousVibrations = mPreviousRingVibrations; + break; + case VibrationAttributes.USAGE_ALARM: + previousVibrations = mPreviousAlarmVibrations; + break; + default: + previousVibrations = mPreviousVibrations; } - if (previousVibrations.size() > mPreviousVibrationsLimit) { previousVibrations.removeFirst(); } @@ -706,17 +603,6 @@ public class VibratorService extends IVibratorService.Stub { } } - private boolean shouldVibrateForPowerModeLocked(Vibration vib) { - if (!mLowPowerMode) { - return true; - } - - int usage = vib.attrs.getUsage(); - return usage == VibrationAttributes.USAGE_RINGTONE - || usage == VibrationAttributes.USAGE_ALARM - || usage == VibrationAttributes.USAGE_COMMUNICATION_REQUEST; - } - /** Scale the vibration effect by the intensity as appropriate based its intent. */ private void applyVibrationIntensityScalingLocked(Vibration vib) { vib.updateEffect(mVibrationScaler.scale(vib.getEffect(), vib.attrs.getUsage())); @@ -744,7 +630,7 @@ public class VibratorService extends IVibratorService.Stub { } private boolean shouldVibrate(Vibration vib) { - if (!shouldVibrateForPowerModeLocked(vib)) { + if (!mVibrationSettings.shouldVibrateForPowerMode(vib.attrs.getUsage())) { endVibrationLocked(vib, Vibration.Status.IGNORED_FOR_POWER); return false; } @@ -755,7 +641,7 @@ public class VibratorService extends IVibratorService.Stub { return false; } - if (isRingtone(vib) && !mVibrationSettings.shouldVibrateForRingtone()) { + if (!mVibrationSettings.shouldVibrateForRingerMode(vib.attrs.getUsage())) { if (DEBUG) { Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones"); } @@ -769,7 +655,7 @@ public class VibratorService extends IVibratorService.Stub { // We might be getting calls from within system_server, so we don't actually // want to throw a SecurityException here. Slog.w(TAG, "Would be an error: vibrate from uid " + vib.uid); - endVibrationLocked(vib, Vibration.Status.ERROR_APP_OPS); + endVibrationLocked(vib, Vibration.Status.IGNORED_ERROR_APP_OPS); } else { endVibrationLocked(vib, Vibration.Status.IGNORED_APP_OPS); } @@ -821,44 +707,11 @@ public class VibratorService extends IVibratorService.Stub { private void updateVibrators() { synchronized (mLock) { - boolean devicesUpdated = mInputDeviceDelegate.updateInputDeviceVibrators( + mInputDeviceDelegate.updateInputDeviceVibrators( mVibrationSettings.shouldVibrateInputDevices()); - boolean lowPowerModeUpdated = updateLowPowerModeLocked(); - - if (devicesUpdated || lowPowerModeUpdated) { - // If the state changes out from under us then just reset. - doCancelVibrateLocked(Vibration.Status.CANCELLED); - } - updateAlwaysOnLocked(); - } - } - - private boolean updateLowPowerModeLocked() { - boolean lowPowerMode = mPowerManagerInternal - .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled; - if (lowPowerMode != mLowPowerMode) { - mLowPowerMode = lowPowerMode; - return true; - } - return false; - } - - private void updateAlwaysOnLocked(int id, Vibration vib) { - VibrationEffect.Prebaked effect; - if (!shouldVibrate(vib)) { - effect = null; - } else { - effect = mVibrationScaler.scale(vib.getEffect(), vib.attrs.getUsage()); - } - mVibratorController.updateAlwaysOn(id, effect); - } - - private void updateAlwaysOnLocked() { - for (int i = 0; i < mAlwaysOnEffects.size(); i++) { - int id = mAlwaysOnEffects.keyAt(i); - Vibration vib = mAlwaysOnEffects.valueAt(i); - updateAlwaysOnLocked(id, vib); + // If the state changes out from under us then just reset. + doCancelVibrateLocked(Vibration.Status.CANCELLED); } } @@ -994,23 +847,10 @@ public class VibratorService extends IVibratorService.Stub { } - private static boolean isNotification(Vibration vib) { - return vib.attrs.getUsage() == VibrationAttributes.USAGE_NOTIFICATION; - } - - private static boolean isRingtone(Vibration vib) { - return vib.attrs.getUsage() == VibrationAttributes.USAGE_RINGTONE; - } - - private static boolean isHapticFeedback(Vibration vib) { - return vib.attrs.getUsage() == VibrationAttributes.USAGE_TOUCH; - } - - private static boolean isAlarm(Vibration vib) { - return vib.attrs.getUsage() == VibrationAttributes.USAGE_ALARM; - } - - private boolean isFromSystem(Vibration vib) { + private boolean isSystemHapticFeedback(Vibration vib) { + if (vib.attrs.getUsage() != VibrationAttributes.USAGE_TOUCH) { + return false; + } return vib.uid == Process.SYSTEM_UID || vib.uid == 0 || mSystemUiPackage.equals(vib.opPkg); } @@ -1050,7 +890,6 @@ public class VibratorService extends IVibratorService.Stub { } else { pw.println("null"); } - pw.println(" mLowPowerMode=" + mLowPowerMode); pw.println(" mVibratorController=" + mVibratorController); pw.println(" mVibrationSettings=" + mVibrationSettings); pw.println(); @@ -1097,7 +936,6 @@ public class VibratorService extends IVibratorService.Stub { proto.write(VibratorServiceDumpProto.IS_VIBRATING, mVibratorController.isVibrating()); proto.write(VibratorServiceDumpProto.VIBRATOR_UNDER_EXTERNAL_CONTROL, mVibratorController.isUnderExternalControl()); - proto.write(VibratorServiceDumpProto.LOW_POWER_MODE, mLowPowerMode); proto.write(VibratorServiceDumpProto.HAPTIC_FEEDBACK_INTENSITY, mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_TOUCH)); proto.write(VibratorServiceDumpProto.HAPTIC_FEEDBACK_DEFAULT_INTENSITY, @@ -1289,7 +1127,7 @@ public class VibratorService extends IVibratorService.Stub { static class Injector { VibratorController createVibratorController(OnVibrationCompleteListener listener) { - return new VibratorController(/* vibratorId= */ 0, listener); + return new VibratorController(/* vibratorId= */ -1, listener); } Handler createHandler(Looper looper) { @@ -1311,9 +1149,7 @@ public class VibratorService extends IVibratorService.Stub { // them. However it may happen that the system is currently playing // haptic feedback as part of the transition. So we don't cancel // system vibrations. - if (mCurrentVibration != null - && !(isHapticFeedback(mCurrentVibration) - && isFromSystem(mCurrentVibration))) { + if (mCurrentVibration != null && !isSystemHapticFeedback(mCurrentVibration)) { doCancelVibrateLocked(Vibration.Status.CANCELLED); } } @@ -1373,7 +1209,7 @@ public class VibratorService extends IVibratorService.Stub { vibHolder.scale = SCALE_MUTE; if (mode == AppOpsManager.MODE_ERRORED) { Slog.w(TAG, "Would be an error: external vibrate from uid " + vib.getUid()); - endVibrationLocked(vibHolder, Vibration.Status.ERROR_APP_OPS); + endVibrationLocked(vibHolder, Vibration.Status.IGNORED_ERROR_APP_OPS); } else { endVibrationLocked(vibHolder, Vibration.Status.IGNORED_APP_OPS); } diff --git a/services/core/java/com/android/server/adb/OWNERS b/services/core/java/com/android/server/adb/OWNERS new file mode 100644 index 000000000000..b97f7956d115 --- /dev/null +++ b/services/core/java/com/android/server/adb/OWNERS @@ -0,0 +1 @@ +include platform/packages/modules/adb:/OWNERS diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index c7e3b2344f54..c364c8463f1b 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -50,6 +50,7 @@ import android.app.ActivityThread; import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.ApplicationExitInfo; +import android.app.BroadcastOptions; import android.app.IApplicationThread; import android.app.IServiceConnection; import android.app.Notification; @@ -3201,7 +3202,8 @@ public final class ActiveServices { + " for fg-service launch"); } mAm.tempWhitelistUidLocked(r.appInfo.uid, - SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch"); + SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch", + BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED); } if (!mPendingServices.contains(r)) { @@ -5283,9 +5285,9 @@ public final class ActiveServices { } if (ret == FGS_FEATURE_DENIED) { - if (mAm.mConstants.mFlagFgsStartTempAllowListEnabled - && mAm.isOnDeviceIdleWhitelistLocked(r.appInfo.uid, false)) { - // uid is on DeviceIdleController's allowlist. + if (mAm.isWhitelistedForFgsStartLocked(r.appInfo.uid)) { + // uid is on DeviceIdleController's user/system allowlist + // or AMS's FgsStartTempAllowList. ret = FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST; } } diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index b4e856bb0706..b0f296f68a47 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -167,13 +167,6 @@ final class ActivityManagerConstants extends ContentObserver { "default_fgs_starts_restriction_enabled"; /** - * Default value for mFlagFgsStartTempAllowListEnabled if not explicitly set in - * Settings.Global. - */ - private static final String KEY_DEFAULT_FGS_STARTS_TEMP_ALLOWLIST_ENABLED = - "default_fgs_starts_temp_allowlist_enabled"; - - /** * Whether FGS notification display is deferred following the transition into * the foreground state. Default behavior is {@code true} unless overridden. */ @@ -372,10 +365,6 @@ final class ActivityManagerConstants extends ContentObserver { // at all. volatile boolean mFlagFgsStartRestrictionEnabled = false; - // When the foreground service background start restriction is enabled, if the app in - // DeviceIdleController's Temp AllowList is allowed to bypass the restriction. - volatile boolean mFlagFgsStartTempAllowListEnabled = false; - // Whether we defer FGS notifications a few seconds following their transition to // the foreground state. Applies only to S+ apps; enabled by default. volatile boolean mFlagFgsNotificationDeferralEnabled = true; @@ -540,9 +529,6 @@ final class ActivityManagerConstants extends ContentObserver { case KEY_DEFAULT_FGS_STARTS_RESTRICTION_ENABLED: updateFgsStartsRestriction(); break; - case KEY_DEFAULT_FGS_STARTS_TEMP_ALLOWLIST_ENABLED: - updateFgsStartsTempAllowList(); - break; case KEY_DEFERRED_FGS_NOTIFICATIONS_ENABLED: updateFgsNotificationDeferralEnable(); break; @@ -809,13 +795,6 @@ final class ActivityManagerConstants extends ContentObserver { /*defaultValue*/ false); } - private void updateFgsStartsTempAllowList() { - mFlagFgsStartTempAllowListEnabled = DeviceConfig.getBoolean( - DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, - KEY_DEFAULT_FGS_STARTS_TEMP_ALLOWLIST_ENABLED, - /*defaultValue*/ false); - } - private void updateFgsNotificationDeferralEnable() { mFlagFgsNotificationDeferralEnabled = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index bcd122d33f7d..2f4373cf473a 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1094,6 +1094,11 @@ public class ActivityManagerService extends IActivityManager.Stub final PendingTempWhitelists mPendingTempWhitelist = new PendingTempWhitelists(this); /** + * The temp-allowlist that is allowed to start FGS from background. + */ + final FgsStartTempAllowList mFgsStartTempAllowList = new FgsStartTempAllowList(); + + /** * Information about and control over application operations */ final AppOpsService mAppOpsService; @@ -5510,6 +5515,12 @@ public class ActivityManagerService extends IActivityManager.Stub || mPendingTempWhitelist.indexOfKey(uid) >= 0; } + boolean isWhitelistedForFgsStartLocked(int uid) { + final int appId = UserHandle.getAppId(uid); + return Arrays.binarySearch(mDeviceIdleExceptIdleWhitelist, appId) >= 0 + || mFgsStartTempAllowList.isAllowed(uid); + } + /** * @return whitelist tag for a uid from mPendingTempWhitelist, null if not currently on * the whitelist @@ -14599,11 +14610,11 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public int getLaunchedFromUid(IBinder activityToken) { - return mActivityTaskManager.getLaunchedFromUid(activityToken); + return ActivityClient.getInstance().getLaunchedFromUid(activityToken); } public String getLaunchedFromPackage(IBinder activityToken) { - return mActivityTaskManager.getLaunchedFromPackage(activityToken); + return ActivityClient.getInstance().getLaunchedFromPackage(activityToken); } // ========================================================= @@ -15324,17 +15335,22 @@ public class ActivityManagerService extends IActivityManager.Stub } } - tempWhitelistUidLocked(targetUid, duration, tag); + tempWhitelistUidLocked(targetUid, duration, tag, + BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED); } /** * Whitelists {@code targetUid} to temporarily bypass Power Save mode. */ @GuardedBy("this") - void tempWhitelistUidLocked(int targetUid, long duration, String tag) { + void tempWhitelistUidLocked(int targetUid, long duration, String tag, int type) { mPendingTempWhitelist.put(targetUid, new PendingTempWhitelist(targetUid, duration, tag)); setUidTempWhitelistStateLocked(targetUid, true); mUiHandler.obtainMessage(PUSH_TEMP_WHITELIST_UI_MSG).sendToTarget(); + + if (type == BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED) { + mFgsStartTempAllowList.add(targetUid, duration); + } } void pushTempWhitelist() { @@ -15688,6 +15704,11 @@ public class ActivityManagerService extends IActivityManager.Stub return mUserController.getCurrentUser(); } + @Override + public @UserIdInt int getCurrentUserId() { + return mUserController.getCurrentUserIdChecked(); + } + String getStartedUserState(int userId) { final UserState userState = mUserController.getStartedUserState(userId); return UserState.stateToString(userState.state); @@ -16306,7 +16327,7 @@ public class ActivityManagerService extends IActivityManager.Stub final ActivityClient ac = ActivityClient.getInstance(); return new ActivityPresentationInfo(ac.getTaskForActivity(token, /*onlyRoot=*/ false), ac.getDisplayId(token), - mActivityTaskManager.getActivityClassForToken(token)); + mAtmInternal.getActivityName(token)); } @Override @@ -17209,8 +17230,6 @@ public class ActivityManagerService extends IActivityManager.Stub throw new SecurityException("Shell can delegate permissions only " + "to one instrumentation at a time"); } - delegate.setPermissions(permissions); - return; } final int instrCount = mActiveInstrumentation.size(); @@ -17253,7 +17272,8 @@ public class ActivityManagerService extends IActivityManager.Stub private class ShellDelegate implements CheckOpsDelegate { private final int mTargetUid; - private @Nullable String[] mPermissions; + @Nullable + private final String[] mPermissions; ShellDelegate(int targetUid, @Nullable String[] permissions) { mTargetUid = targetUid; @@ -17264,19 +17284,15 @@ public class ActivityManagerService extends IActivityManager.Stub return mTargetUid; } - void setPermissions(@Nullable String[] permissions) { - mPermissions = permissions; - PackageManager.invalidatePackageInfoCache(); - } - @Override public int checkOperation(int code, int uid, String packageName, boolean raw, QuadFunction<Integer, Integer, String, Boolean, Integer> superImpl) { if (uid == mTargetUid && isTargetOp(code)) { + final int shellUid = UserHandle.getUid(UserHandle.getUserId(uid), + Process.SHELL_UID); final long identity = Binder.clearCallingIdentity(); try { - return superImpl.apply(code, Process.SHELL_UID, - "com.android.shell", raw); + return superImpl.apply(code, shellUid, "com.android.shell", raw); } finally { Binder.restoreCallingIdentity(identity); } @@ -17288,10 +17304,11 @@ public class ActivityManagerService extends IActivityManager.Stub public int checkAudioOperation(int code, int usage, int uid, String packageName, QuadFunction<Integer, Integer, Integer, String, Integer> superImpl) { if (uid == mTargetUid && isTargetOp(code)) { + final int shellUid = UserHandle.getUid(UserHandle.getUserId(uid), + Process.SHELL_UID); final long identity = Binder.clearCallingIdentity(); try { - return superImpl.apply(code, usage, Process.SHELL_UID, - "com.android.shell"); + return superImpl.apply(code, usage, shellUid, "com.android.shell"); } finally { Binder.restoreCallingIdentity(identity); } @@ -17306,9 +17323,11 @@ public class ActivityManagerService extends IActivityManager.Stub @NonNull HeptFunction<Integer, Integer, String, String, Boolean, String, Boolean, Integer> superImpl) { if (uid == mTargetUid && isTargetOp(code)) { + final int shellUid = UserHandle.getUid(UserHandle.getUserId(uid), + Process.SHELL_UID); final long identity = Binder.clearCallingIdentity(); try { - return superImpl.apply(code, Process.SHELL_UID, "com.android.shell", featureId, + return superImpl.apply(code, shellUid, "com.android.shell", featureId, shouldCollectAsyncNotedOp, message, shouldCollectMessage); } finally { Binder.restoreCallingIdentity(identity); diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index e3c071fe10e2..12fe3eda78a4 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -118,7 +118,6 @@ import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Locale; -import java.util.Objects; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -1842,9 +1841,11 @@ final class ActivityManagerShellCommand extends ShellCommand { } int runGetCurrentUser(PrintWriter pw) throws RemoteException { - UserInfo currentUser = Objects.requireNonNull(mInterface.getCurrentUser(), - "Current user not set"); - pw.println(currentUser.id); + int userId = mInterface.getCurrentUserId(); + if (userId == UserHandle.USER_NULL) { + throw new IllegalStateException("Current user not set"); + } + pw.println(userId); return 0; } diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 3b6f0ac42ed2..422ae685cfa9 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -261,6 +261,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub mStats.setRadioScanningTimeoutLocked(mContext.getResources().getInteger( com.android.internal.R.integer.config_radioScanningTimeout) * 1000L); mStats.setPowerProfileLocked(new PowerProfile(context)); + mStats.startTrackingSystemServerCpuTime(); + mBatteryUsageStatsProvider = new BatteryUsageStatsProvider(context, mStats); } diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 0877dd96c19f..d2ee69e0e00d 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -896,7 +896,8 @@ public final class BroadcastQueue { return false; } - final void scheduleTempWhitelistLocked(int uid, long duration, BroadcastRecord r) { + final void scheduleTempWhitelistLocked(int uid, long duration, BroadcastRecord r, + @BroadcastOptions.TempAllowListType int type) { if (duration > Integer.MAX_VALUE) { duration = Integer.MAX_VALUE; } @@ -919,9 +920,9 @@ public final class BroadcastQueue { } if (DEBUG_BROADCAST) { Slog.v(TAG, "Broadcast temp whitelist uid=" + uid + " duration=" + duration - + " : " + b.toString()); + + " type=" + type + " : " + b.toString()); } - mService.tempWhitelistUidLocked(uid, duration, b.toString()); + mService.tempWhitelistUidLocked(uid, duration, b.toString(), type); } /** @@ -1318,7 +1319,8 @@ public final class BroadcastQueue { } if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) { scheduleTempWhitelistLocked(filter.owningUid, - brOptions.getTemporaryAppWhitelistDuration(), r); + brOptions.getTemporaryAppWhitelistDuration(), r, + brOptions.getTemporaryAppWhitelistType()); } } return; @@ -1610,7 +1612,8 @@ public final class BroadcastQueue { (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0); if (isActivityCapable) { scheduleTempWhitelistLocked(receiverUid, - brOptions.getTemporaryAppWhitelistDuration(), r); + brOptions.getTemporaryAppWhitelistDuration(), r, + brOptions.getTemporaryAppWhitelistType()); } // Broadcast is being executed, its package can't be stopped. diff --git a/services/core/java/com/android/server/am/FgsStartTempAllowList.java b/services/core/java/com/android/server/am/FgsStartTempAllowList.java new file mode 100644 index 000000000000..1f9039392405 --- /dev/null +++ b/services/core/java/com/android/server/am/FgsStartTempAllowList.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.am; + +import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; + +import android.os.SystemClock; +import android.util.Slog; +import android.util.SparseLongArray; + +/** + * List of uids that are temporarily allowed to start FGS from background. + */ +final class FgsStartTempAllowList { + private static final int MAX_SIZE = 100; + /** + * The key is the UID, the value is expiration elapse time in ms of this temp-allowed UID. + */ + private final SparseLongArray mTempAllowListFgs = new SparseLongArray(); + + FgsStartTempAllowList() { + } + + void add(int uid, long duration) { + if (duration <= 0) { + Slog.e(TAG_AM, "FgsStartTempAllowList bad duration:" + duration + " uid: " + uid); + return; + } + // The temp allowlist should be a short list with only a few entries in it. + final int size = mTempAllowListFgs.size(); + if (size > MAX_SIZE) { + Slog.w(TAG_AM, "FgsStartTempAllowList length:" + size + " exceeds " + MAX_SIZE); + } + final long now = SystemClock.elapsedRealtime(); + for (int index = mTempAllowListFgs.size() - 1; index >= 0; index--) { + if (mTempAllowListFgs.valueAt(index) < now) { + mTempAllowListFgs.removeAt(index); + } + } + final long existingExpirationTime = mTempAllowListFgs.get(uid, -1); + final long expirationTime = now + duration; + if (existingExpirationTime == -1 || existingExpirationTime < expirationTime) { + mTempAllowListFgs.put(uid, expirationTime); + } + } + + boolean isAllowed(int uid) { + final int index = mTempAllowListFgs.indexOfKey(uid); + if (index < 0) { + return false; + } else if (mTempAllowListFgs.valueAt(index) < SystemClock.elapsedRealtime()) { + mTempAllowListFgs.removeAt(index); + return false; + } else { + return true; + } + } +} diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS index 60530c4eb920..9e79b02f8c96 100644 --- a/services/core/java/com/android/server/am/OWNERS +++ b/services/core/java/com/android/server/am/OWNERS @@ -23,6 +23,8 @@ toddke@google.com # Battery Stats joeo@google.com +per-file BatteryStats* = file:/BATTERY_STATS_OWNERS +per-file BatteryExternalStats* = file:/BATTERY_STATS_OWNERS # Londoners michaelwr@google.com diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 12fcc9cc26bf..c04f6ff37229 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -2173,7 +2173,7 @@ class UserController implements Handler.Callback { } } - UserInfo getCurrentUser() { + private void checkGetCurrentUserPermissions() { if ((mInjector.checkCallingPermission(INTERACT_ACROSS_USERS) != PackageManager.PERMISSION_GRANTED) && ( mInjector.checkCallingPermission(INTERACT_ACROSS_USERS_FULL) @@ -2185,8 +2185,12 @@ class UserController implements Handler.Callback { Slog.w(TAG, msg); throw new SecurityException(msg); } + } - // Optimization - if there is no pending user switch, return current id + UserInfo getCurrentUser() { + checkGetCurrentUserPermissions(); + + // Optimization - if there is no pending user switch, return user for current id // (no need to acquire lock because mTargetUserId and mCurrentUserId are volatile) if (mTargetUserId == UserHandle.USER_NULL) { return getUserInfo(mCurrentUserId); @@ -2196,9 +2200,23 @@ class UserController implements Handler.Callback { } } + /** + * Gets the current user id, but checking that caller has the proper permissions. + */ + int getCurrentUserIdChecked() { + checkGetCurrentUserPermissions(); + + // Optimization - if there is no pending user switch, return current id + // (no need to acquire lock because mTargetUserId and mCurrentUserId are volatile) + if (mTargetUserId == UserHandle.USER_NULL) { + return mCurrentUserId; + } + return getCurrentOrTargetUserId(); + } + @GuardedBy("mLock") UserInfo getCurrentUserLU() { - int userId = mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId; + int userId = getCurrentOrTargetUserIdLU(); return getUserInfo(userId); } @@ -2213,7 +2231,6 @@ class UserController implements Handler.Callback { return mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId; } - @GuardedBy("mLock") int getCurrentUserIdLU() { return mCurrentUserId; diff --git a/services/core/java/com/android/server/appop/OWNERS b/services/core/java/com/android/server/appop/OWNERS new file mode 100644 index 000000000000..999ea0e62a0a --- /dev/null +++ b/services/core/java/com/android/server/appop/OWNERS @@ -0,0 +1 @@ +include /core/java/android/permission/OWNERS diff --git a/services/core/java/com/android/server/attention/OWNERS b/services/core/java/com/android/server/attention/OWNERS new file mode 100644 index 000000000000..51fc9bd09e4f --- /dev/null +++ b/services/core/java/com/android/server/attention/OWNERS @@ -0,0 +1 @@ +include /core/java/android/attention/OWNERS diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 4d971a51e885..6bc927a5176f 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -2108,6 +2108,12 @@ public class AudioService extends IAudioService.Stub return getDevicesForAttributesInt(attributes); } + /** @see AudioManager#isMusicActive() */ + public boolean isMusicActive() { + // no permission required + return AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0); + } + protected @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributesInt( @NonNull AudioAttributes attributes) { Objects.requireNonNull(attributes); @@ -7444,8 +7450,8 @@ public class AudioService extends IAudioService.Stub private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000; // 30s after boot completed - // check playback or record activity every 3 seconds for UIDs owning mode IN_COMMUNICATION - private static final int CHECK_MODE_FOR_UID_PERIOD_MS = 3000; + // check playback or record activity every 6 seconds for UIDs owning mode IN_COMMUNICATION + private static final int CHECK_MODE_FOR_UID_PERIOD_MS = 6000; private int safeMediaVolumeIndex(int device) { if (!mSafeMediaVolumeDevices.contains(device)) { diff --git a/services/core/java/com/android/server/audio/TEST_MAPPING b/services/core/java/com/android/server/audio/TEST_MAPPING index 0d34c5372914..90246f849491 100644 --- a/services/core/java/com/android/server/audio/TEST_MAPPING +++ b/services/core/java/com/android/server/audio/TEST_MAPPING @@ -1,5 +1,5 @@ { - "presubmit": [ + "presubmit-large": [ { "name": "CtsMediaTestCases", "options": [ diff --git a/services/core/java/com/android/server/backup/OWNERS b/services/core/java/com/android/server/backup/OWNERS new file mode 100644 index 000000000000..d99779e3d9da --- /dev/null +++ b/services/core/java/com/android/server/backup/OWNERS @@ -0,0 +1 @@ +include /services/backup/OWNERS diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java index ce880aa8aeed..cbffdd33fff0 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java @@ -198,9 +198,11 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> { final Intent intent = new Intent("android.settings.FACE_SETTINGS"); intent.setPackage("com.android.settings"); + // TODO(b/174187097) Please replace FLAG_MUTABLE_UNAUDITED below + // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(getContext(), - 0 /* requestCode */, intent, 0 /* flags */, null /* options */, - UserHandle.CURRENT); + 0 /* requestCode */, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED /* flags */, + null /* options */, UserHandle.CURRENT); final String channelName = "FaceEnrollNotificationChannel"; diff --git a/services/core/java/com/android/server/camera/OWNERS b/services/core/java/com/android/server/camera/OWNERS new file mode 100644 index 000000000000..f48a95c5b3a3 --- /dev/null +++ b/services/core/java/com/android/server/camera/OWNERS @@ -0,0 +1 @@ +include platform/frameworks/av:/camera/OWNERS diff --git a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java index 4fb6607a6b08..995bb2422de2 100644 --- a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java +++ b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java @@ -166,7 +166,7 @@ public class DefaultNetworkMetrics { private static void fillLinkInfo(DefaultNetworkEvent ev, NetworkAgentInfo nai) { LinkProperties lp = nai.linkProperties; - ev.netId = nai.network().netId; + ev.netId = nai.network().getNetId(); ev.transports |= BitUtils.packBits(nai.networkCapabilities.getTransportTypes()); ev.ipv4 |= lp.hasIpv4Address() && lp.hasIpv4DefaultRoute(); ev.ipv6 |= lp.hasGlobalIpv6Address() && lp.hasIpv6DefaultRoute(); diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java index 1f0fb5e006b8..c70bb080b0b1 100644 --- a/services/core/java/com/android/server/connectivity/DnsManager.java +++ b/services/core/java/com/android/server/connectivity/DnsManager.java @@ -34,7 +34,6 @@ import android.content.Intent; import android.net.IDnsResolver; import android.net.LinkProperties; import android.net.Network; -import android.net.NetworkUtils; import android.net.ResolverOptionsParcel; import android.net.ResolverParamsParcel; import android.net.Uri; @@ -50,6 +49,7 @@ import android.util.Pair; import java.net.InetAddress; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -59,7 +59,6 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; - /** * Encapsulate the management of DNS settings for networks. * @@ -266,23 +265,23 @@ public class DnsManager { } public void removeNetwork(Network network) { - mPrivateDnsMap.remove(network.netId); - mPrivateDnsValidationMap.remove(network.netId); - mTransportsMap.remove(network.netId); - mLinkPropertiesMap.remove(network.netId); + mPrivateDnsMap.remove(network.getNetId()); + mPrivateDnsValidationMap.remove(network.getNetId()); + mTransportsMap.remove(network.getNetId()); + mLinkPropertiesMap.remove(network.getNetId()); } // This is exclusively called by ConnectivityService#dumpNetworkDiagnostics() which // is not on the ConnectivityService handler thread. public PrivateDnsConfig getPrivateDnsConfig(@NonNull Network network) { - return mPrivateDnsMap.getOrDefault(network.netId, PRIVATE_DNS_OFF); + return mPrivateDnsMap.getOrDefault(network.getNetId(), PRIVATE_DNS_OFF); } public PrivateDnsConfig updatePrivateDns(Network network, PrivateDnsConfig cfg) { Log.w(TAG, "updatePrivateDns(" + network + ", " + cfg + ")"); return (cfg != null) - ? mPrivateDnsMap.put(network.netId, cfg) - : mPrivateDnsMap.remove(network.netId); + ? mPrivateDnsMap.put(network.getNetId(), cfg) + : mPrivateDnsMap.remove(network.getNetId()); } public void updatePrivateDnsStatus(int netId, LinkProperties lp) { @@ -309,8 +308,7 @@ public class DnsManager { } public void updatePrivateDnsValidation(PrivateDnsValidationUpdate update) { - final PrivateDnsValidationStatuses statuses = - mPrivateDnsValidationMap.get(update.netId); + final PrivateDnsValidationStatuses statuses = mPrivateDnsValidationMap.get(update.netId); if (statuses == null) return; statuses.updateStatus(update); } @@ -364,12 +362,11 @@ public class DnsManager { paramsParcel.successThreshold = mSuccessThreshold; paramsParcel.minSamples = mMinSamples; paramsParcel.maxSamples = mMaxSamples; - paramsParcel.servers = - NetworkUtils.makeStrings(lp.getDnsServers()); + paramsParcel.servers = makeStrings(lp.getDnsServers()); paramsParcel.domains = getDomainStrings(lp.getDomains()); paramsParcel.tlsName = strictMode ? privateDnsCfg.hostname : ""; paramsParcel.tlsServers = - strictMode ? NetworkUtils.makeStrings( + strictMode ? makeStrings( Arrays.stream(privateDnsCfg.ips) .filter((ip) -> lp.isReachable(ip)) .collect(Collectors.toList())) @@ -460,6 +457,21 @@ public class DnsManager { return Settings.Global.getInt(mContentResolver, which, dflt); } + /** + * Create a string array of host addresses from a collection of InetAddresses + * + * @param addrs a Collection of InetAddresses + * @return an array of Strings containing their host addresses + */ + private String[] makeStrings(Collection<InetAddress> addrs) { + String[] result = new String[addrs.size()]; + int i = 0; + for (InetAddress addr : addrs) { + result[i++] = addr.getHostAddress(); + } + return result; + } + private static String getPrivateDnsMode(ContentResolver cr) { String mode = getStringSetting(cr, PRIVATE_DNS_MODE); if (TextUtils.isEmpty(mode)) mode = getStringSetting(cr, PRIVATE_DNS_DEFAULT_MODE); diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java index 8625a6f470c5..96cbfde2a0a0 100644 --- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java +++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java @@ -40,11 +40,11 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.net.ISocketKeepaliveCallback; +import android.net.InetAddresses; import android.net.InvalidPacketException; import android.net.KeepalivePacketData; import android.net.NattKeepalivePacketData; import android.net.NetworkAgent; -import android.net.NetworkUtils; import android.net.SocketKeepalive.InvalidSocketException; import android.net.TcpKeepalivePacketData; import android.net.util.KeepaliveUtils; @@ -625,8 +625,8 @@ public class KeepaliveTracker { InetAddress srcAddress, dstAddress; try { - srcAddress = NetworkUtils.numericToInetAddress(srcAddrString); - dstAddress = NetworkUtils.numericToInetAddress(dstAddrString); + srcAddress = InetAddresses.parseNumericAddress(srcAddrString); + dstAddress = InetAddresses.parseNumericAddress(dstAddrString); } catch (IllegalArgumentException e) { notifyErrorCallback(cb, ERROR_INVALID_IP_ADDRESS); return; diff --git a/services/core/java/com/android/server/connectivity/LingerMonitor.java b/services/core/java/com/android/server/connectivity/LingerMonitor.java index f99f4c65594b..adec7ad5c89d 100644 --- a/services/core/java/com/android/server/connectivity/LingerMonitor.java +++ b/services/core/java/com/android/server/connectivity/LingerMonitor.java @@ -114,7 +114,7 @@ public class LingerMonitor { private int getNotificationSource(NetworkAgentInfo toNai) { for (int i = 0; i < mNotifications.size(); i++) { - if (mNotifications.valueAt(i) == toNai.network.netId) { + if (mNotifications.valueAt(i) == toNai.network.getNetId()) { return mNotifications.keyAt(i); } } @@ -122,7 +122,7 @@ public class LingerMonitor { } private boolean everNotified(NetworkAgentInfo nai) { - return mEverNotified.get(nai.network.netId, false); + return mEverNotified.get(nai.network.getNetId(), false); } @VisibleForTesting @@ -153,7 +153,7 @@ public class LingerMonitor { } private void showNotification(NetworkAgentInfo fromNai, NetworkAgentInfo toNai) { - mNotifier.showNotification(fromNai.network.netId, NotificationType.NETWORK_SWITCH, + mNotifier.showNotification(fromNai.network.getNetId(), NotificationType.NETWORK_SWITCH, fromNai, toNai, createNotificationIntent(), true); } @@ -208,8 +208,8 @@ public class LingerMonitor { + " type=" + sNotifyTypeNames.get(notifyType, "unknown(" + notifyType + ")")); } - mNotifications.put(fromNai.network.netId, toNai.network.netId); - mEverNotified.put(fromNai.network.netId, true); + mNotifications.put(fromNai.network.getNetId(), toNai.network.getNetId()); + mEverNotified.put(fromNai.network.getNetId(), true); } /** @@ -295,8 +295,8 @@ public class LingerMonitor { } public void noteDisconnect(NetworkAgentInfo nai) { - mNotifications.delete(nai.network.netId); - mEverNotified.delete(nai.network.netId); + mNotifications.delete(nai.network.getNetId()); + mEverNotified.delete(nai.network.getNetId()); maybeStopNotifying(nai); // No need to cancel notifications on nai: NetworkMonitor does that on disconnect. } diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index d9c2e80aadcd..c1b1b6a2f26c 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -528,6 +528,6 @@ public class Nat464Xlat extends BaseNetworkObserver { @VisibleForTesting protected int getNetId() { - return mNetwork.network.netId; + return mNetwork.network.getNetId(); } } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 3270dd55218c..ccd1f3bb16f6 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -610,7 +610,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { if (newExpiry > 0) { mLingerMessage = new WakeupMessage( mContext, mHandler, - "NETWORK_LINGER_COMPLETE." + network.netId /* cmdName */, + "NETWORK_LINGER_COMPLETE." + network.getNetId() /* cmdName */, EVENT_NETWORK_LINGER_COMPLETE /* cmd */, 0 /* arg1 (unused) */, 0 /* arg2 (unused) */, this /* obj (NetworkAgentInfo) */); @@ -701,7 +701,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { * This represents the network with something like "[100 WIFI|VPN]" or "[108 MOBILE]". */ public String toShortString() { - return "[" + network.netId + " " + return "[" + network.getNetId() + " " + transportNamesOf(networkCapabilities.getTransportTypes()) + "]"; } diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java index 49c16ad96eb7..a7be657ae7a3 100644 --- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java +++ b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java @@ -20,10 +20,10 @@ import static android.system.OsConstants.*; import android.annotation.NonNull; import android.annotation.Nullable; +import android.net.InetAddresses; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.Network; -import android.net.NetworkUtils; import android.net.RouteInfo; import android.net.TrafficStats; import android.net.shared.PrivateDnsConfig; @@ -97,8 +97,8 @@ import javax.net.ssl.SSLSocketFactory; public class NetworkDiagnostics { private static final String TAG = "NetworkDiagnostics"; - private static final InetAddress TEST_DNS4 = NetworkUtils.numericToInetAddress("8.8.8.8"); - private static final InetAddress TEST_DNS6 = NetworkUtils.numericToInetAddress( + private static final InetAddress TEST_DNS4 = InetAddresses.parseNumericAddress("8.8.8.8"); + private static final InetAddress TEST_DNS6 = InetAddresses.parseNumericAddress( "2001:4860:4860::8888"); // For brevity elsewhere. diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 3445275b76dd..5cb0994c5cb2 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -1062,7 +1062,7 @@ public class Vpn { if (null == agent) return NETID_UNSET; final Network network = agent.getNetwork(); if (null == network) return NETID_UNSET; - return network.netId; + return network.getNetId(); } private LinkProperties makeLinkProperties() { @@ -1778,7 +1778,7 @@ public class Vpn { if (networks[i] == null) { mConfig.underlyingNetworks[i] = null; } else { - mConfig.underlyingNetworks[i] = new Network(networks[i].netId); + mConfig.underlyingNetworks[i] = new Network(networks[i].getNetId()); } } } diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index 0b2d4d70ae1e..6ae410a49786 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -3838,9 +3838,12 @@ public class SyncManager { } UserHandle user = new UserHandle(userId); + // TODO(b/174186839) Please replace FLAG_MUTABLE_UNAUDITED below + // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. final PendingIntent pendingIntent = PendingIntent .getActivityAsUser(mContext, 0, clickIntent, - PendingIntent.FLAG_CANCEL_CURRENT, null, user); + PendingIntent.FLAG_CANCEL_CURRENT + | PendingIntent.FLAG_MUTABLE_UNAUDITED, null, user); CharSequence tooManyDeletesDescFormat = mContext.getResources().getText( R.string.contentServiceTooManyDeletesNotificationDesc); diff --git a/services/core/java/com/android/server/contentcapture/OWNERS b/services/core/java/com/android/server/contentcapture/OWNERS new file mode 100644 index 000000000000..a28e00a5c490 --- /dev/null +++ b/services/core/java/com/android/server/contentcapture/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/contentcapture/OWNERS diff --git a/services/core/java/com/android/server/dreams/OWNERS b/services/core/java/com/android/server/dreams/OWNERS index 426f002ad236..3c9bbf8797ea 100644 --- a/services/core/java/com/android/server/dreams/OWNERS +++ b/services/core/java/com/android/server/dreams/OWNERS @@ -1,3 +1,3 @@ -dsandler@android.com +dsandler@google.com michaelwr@google.com roosa@google.com diff --git a/services/core/java/com/android/server/hdmi/HdmiCecConfig.java b/services/core/java/com/android/server/hdmi/HdmiCecConfig.java index 98d130f1ef69..371fd3d33090 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecConfig.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecConfig.java @@ -85,7 +85,7 @@ public class HdmiCecConfig { @NonNull private final Context mContext; @NonNull private final StorageAdapter mStorageAdapter; - @Nullable private final CecSettings mProductConfig; + @Nullable private final CecSettings mSystemConfig; @Nullable private final CecSettings mVendorOverride; /** @@ -162,14 +162,14 @@ public class HdmiCecConfig { @VisibleForTesting HdmiCecConfig(@NonNull Context context, @NonNull StorageAdapter storageAdapter, - @Nullable CecSettings productConfig, + @Nullable CecSettings systemConfig, @Nullable CecSettings vendorOverride) { mContext = context; mStorageAdapter = storageAdapter; - mProductConfig = productConfig; + mSystemConfig = systemConfig; mVendorOverride = vendorOverride; - if (mProductConfig == null) { - Slog.i(TAG, "CEC master configuration XML missing."); + if (mSystemConfig == null) { + Slog.i(TAG, "CEC system configuration XML missing."); } if (mVendorOverride == null) { Slog.i(TAG, "CEC OEM configuration override XML missing."); @@ -178,7 +178,7 @@ public class HdmiCecConfig { HdmiCecConfig(@NonNull Context context) { this(context, new StorageAdapter(context), - readSettingsFromFile(Environment.buildPath(Environment.getProductDirectory(), + readSettingsFromFile(Environment.buildPath(Environment.getRootDirectory(), ETC_DIR, CONFIG_FILE)), readSettingsFromFile(Environment.buildPath(Environment.getVendorDirectory(), ETC_DIR, CONFIG_FILE))); @@ -226,7 +226,7 @@ public class HdmiCecConfig { @Nullable private Setting getSetting(@NonNull String name) { - if (mProductConfig == null) { + if (mSystemConfig == null) { return null; } if (mVendorOverride != null) { @@ -237,8 +237,8 @@ public class HdmiCecConfig { } } } - // If not found, try the product config. - for (Setting setting : mProductConfig.getSetting()) { + // If not found, try the system config. + for (Setting setting : mSystemConfig.getSetting()) { if (setting.getName().equals(name)) { return setting; } @@ -322,11 +322,11 @@ public class HdmiCecConfig { * Returns a list of all settings based on the XML metadata. */ public @CecSettingName List<String> getAllSettings() { - if (mProductConfig == null) { + if (mSystemConfig == null) { return new ArrayList<String>(); } List<String> allSettings = new ArrayList<String>(); - for (Setting setting : mProductConfig.getSetting()) { + for (Setting setting : mSystemConfig.getSetting()) { allSettings.add(setting.getName()); } return allSettings; @@ -336,12 +336,12 @@ public class HdmiCecConfig { * Returns a list of user-modifiable settings based on the XML metadata. */ public @CecSettingName List<String> getUserSettings() { - if (mProductConfig == null) { + if (mSystemConfig == null) { return new ArrayList<String>(); } Set<String> userSettings = new HashSet<String>(); - // First read from the product config. - for (Setting setting : mProductConfig.getSetting()) { + // First read from the system config. + for (Setting setting : mSystemConfig.getSetting()) { if (setting.getUserConfigurable()) { userSettings.add(setting.getName()); } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index 9b3f788d7457..0e196f278ddf 100755 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -282,6 +282,8 @@ abstract class HdmiCecLocalDevice { return handleGiveOsdName(message); case Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID: return handleGiveDeviceVendorId(null); + case Constants.MESSAGE_CEC_VERSION: + return handleCecVersion(); case Constants.MESSAGE_GET_CEC_VERSION: return handleGetCecVersion(message); case Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS: @@ -406,6 +408,14 @@ abstract class HdmiCecLocalDevice { } @ServiceThreadOnly + private boolean handleCecVersion() { + assertRunOnServiceThread(); + + // Return true to avoid <Feature Abort> responses. Cec Version is tracked in HdmiCecNetwork. + return true; + } + + @ServiceThreadOnly protected boolean handleActiveSource(HdmiCecMessage message) { return false; } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java index fc21724714c5..b748ae026cfc 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java @@ -166,7 +166,6 @@ public class HdmiCecNetwork { } return false; } - /** * Clear all logical addresses registered in the device. * @@ -523,11 +522,32 @@ public class HdmiCecNetwork { case Constants.MESSAGE_DEVICE_VENDOR_ID: handleDeviceVendorId(message); break; - + case Constants.MESSAGE_CEC_VERSION: + handleCecVersion(message); + break; + case Constants.MESSAGE_REPORT_FEATURES: + handleReportFeatures(message); + break; } } @ServiceThreadOnly + private void handleReportFeatures(HdmiCecMessage message) { + assertRunOnServiceThread(); + + int version = Byte.toUnsignedInt(message.getParams()[0]); + updateDeviceCecVersion(message.getSource(), version); + } + + @ServiceThreadOnly + private void handleCecVersion(HdmiCecMessage message) { + assertRunOnServiceThread(); + + int version = Byte.toUnsignedInt(message.getParams()[0]); + updateDeviceCecVersion(message.getSource(), version); + } + + @ServiceThreadOnly private void handleReportPhysicalAddress(HdmiCecMessage message) { assertRunOnServiceThread(); int logicalAddress = message.getSource(); @@ -543,7 +563,8 @@ public class HdmiCecNetwork { HdmiDeviceInfo updatedDeviceInfo = new HdmiDeviceInfo(deviceInfo.getLogicalAddress(), physicalAddress, physicalAddressToPortId(physicalAddress), type, deviceInfo.getVendorId(), - deviceInfo.getDisplayName(), deviceInfo.getDevicePowerStatus()); + deviceInfo.getDisplayName(), deviceInfo.getDevicePowerStatus(), + deviceInfo.getCecVersion()); updateCecDevice(updatedDeviceInfo); } } @@ -554,6 +575,31 @@ public class HdmiCecNetwork { // Update power status of device int newStatus = message.getParams()[0] & 0xFF; updateDevicePowerStatus(message.getSource(), newStatus); + + if (message.getDestination() == Constants.ADDR_BROADCAST) { + updateDeviceCecVersion(message.getSource(), HdmiControlManager.HDMI_CEC_VERSION_2_0); + } + } + + @ServiceThreadOnly + private void updateDeviceCecVersion(int logicalAddress, int hdmiCecVersion) { + assertRunOnServiceThread(); + HdmiDeviceInfo deviceInfo = getCecDeviceInfo(logicalAddress); + if (deviceInfo == null) { + Slog.w(TAG, "Can not update CEC version of non-existing device:" + logicalAddress); + return; + } + + if (deviceInfo.getCecVersion() == hdmiCecVersion) { + return; + } + + HdmiDeviceInfo updatedDeviceInfo = new HdmiDeviceInfo(deviceInfo.getLogicalAddress(), + deviceInfo.getPhysicalAddress(), deviceInfo.getPortId(), deviceInfo.getDeviceType(), + deviceInfo.getVendorId(), + deviceInfo.getDisplayName(), deviceInfo.getDevicePowerStatus(), + hdmiCecVersion); + updateCecDevice(updatedDeviceInfo); } @ServiceThreadOnly @@ -586,7 +632,7 @@ public class HdmiCecNetwork { updateCecDevice(new HdmiDeviceInfo(deviceInfo.getLogicalAddress(), deviceInfo.getPhysicalAddress(), deviceInfo.getPortId(), deviceInfo.getDeviceType(), deviceInfo.getVendorId(), osdName, - deviceInfo.getDevicePowerStatus())); + deviceInfo.getDevicePowerStatus(), deviceInfo.getCecVersion())); } @ServiceThreadOnly @@ -602,7 +648,8 @@ public class HdmiCecNetwork { HdmiDeviceInfo updatedDeviceInfo = new HdmiDeviceInfo(deviceInfo.getLogicalAddress(), deviceInfo.getPhysicalAddress(), deviceInfo.getPortId(), deviceInfo.getDeviceType(), vendorId, - deviceInfo.getDisplayName(), deviceInfo.getDevicePowerStatus()); + deviceInfo.getDisplayName(), deviceInfo.getDevicePowerStatus(), + deviceInfo.getCecVersion()); updateCecDevice(updatedDeviceInfo); } } diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index a1d13e974019..c943fbcdee2e 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -813,7 +813,7 @@ public class HdmiControlService extends SystemService { // with system. HdmiDeviceInfo deviceInfo = createDeviceInfo(logicalAddress, deviceType, - HdmiControlManager.POWER_STATUS_ON); + HdmiControlManager.POWER_STATUS_ON, getCecVersion()); localDevice.setDeviceInfo(deviceInfo); mHdmiCecNetwork.addLocalDevice(deviceType, localDevice); mCecController.addLogicalAddress(logicalAddress); @@ -1222,11 +1222,12 @@ public class HdmiControlService extends SystemService { } } - private HdmiDeviceInfo createDeviceInfo(int logicalAddress, int deviceType, int powerStatus) { + private HdmiDeviceInfo createDeviceInfo(int logicalAddress, int deviceType, int powerStatus, + int cecVersion) { String displayName = readStringSetting(Global.DEVICE_NAME, Build.MODEL); return new HdmiDeviceInfo(logicalAddress, getPhysicalAddress(), pathToPortId(getPhysicalAddress()), deviceType, - getVendorId(), displayName, powerStatus); + getVendorId(), displayName, powerStatus, cecVersion); } // Set the display name in HdmiDeviceInfo of the current devices to content provided by @@ -1240,7 +1241,7 @@ public class HdmiControlService extends SystemService { device.setDeviceInfo(new HdmiDeviceInfo( deviceInfo.getLogicalAddress(), deviceInfo.getPhysicalAddress(), deviceInfo.getPortId(), deviceInfo.getDeviceType(), deviceInfo.getVendorId(), - newDisplayName, deviceInfo.getDevicePowerStatus())); + newDisplayName, deviceInfo.getDevicePowerStatus(), deviceInfo.getCecVersion())); sendCecCommand(HdmiCecMessageBuilder.buildSetOsdNameCommand( device.mAddress, Constants.ADDR_TV, newDisplayName)); } diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java index 52a804a36750..03e5de8ac8bd 100644 --- a/services/core/java/com/android/server/hdmi/HdmiUtils.java +++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java @@ -396,7 +396,7 @@ final class HdmiUtils { static HdmiDeviceInfo cloneHdmiDeviceInfo(HdmiDeviceInfo info, int newPowerStatus) { return new HdmiDeviceInfo(info.getLogicalAddress(), info.getPhysicalAddress(), info.getPortId(), info.getDeviceType(), - info.getVendorId(), info.getDisplayName(), newPowerStatus); + info.getVendorId(), info.getDisplayName(), newPowerStatus, info.getCecVersion()); } /** diff --git a/services/core/java/com/android/server/hdmi/OWNERS b/services/core/java/com/android/server/hdmi/OWNERS new file mode 100644 index 000000000000..c3c47eda59d7 --- /dev/null +++ b/services/core/java/com/android/server/hdmi/OWNERS @@ -0,0 +1 @@ +include /core/java/android/hardware/hdmi/OWNERS diff --git a/services/core/java/com/android/server/hdmi/cec_config.xml b/services/core/java/com/android/server/hdmi/cec_config.xml new file mode 100644 index 000000000000..480e0ec040a8 --- /dev/null +++ b/services/core/java/com/android/server/hdmi/cec_config.xml @@ -0,0 +1,49 @@ +<?xml version='1.0' encoding='utf-8' standalone='yes' ?> +<cec-settings> + <setting name="hdmi_cec_enabled" + value-type="int" + user-configurable="true"> + <allowed-values> + <value int-value="0" /> + <value int-value="1" /> + </allowed-values> + <default-value int-value="1" /> + </setting> + <setting name="hdmi_cec_version" + value-type="int" + user-configurable="true"> + <allowed-values> + <value int-value="0x05" /> + <value int-value="0x06" /> + </allowed-values> + <default-value int-value="0x05" /> + </setting> + <setting name="send_standby_on_sleep" + value-type="string" + user-configurable="true"> + <allowed-values> + <value string-value="to_tv" /> + <value string-value="broadcast" /> + <value string-value="none" /> + </allowed-values> + <default-value string-value="to_tv" /> + </setting> + <setting name="power_state_change_on_active_source_lost" + value-type="string" + user-configurable="true"> + <allowed-values> + <value string-value="none" /> + <value string-value="standby_now" /> + </allowed-values> + <default-value string-value="none" /> + </setting> + <setting name="system_audio_mode_muting" + value-type="int" + user-configurable="true"> + <allowed-values> + <value int-value="0" /> + <value int-value="1" /> + </allowed-values> + <default-value int-value="1" /> + </setting> +</cec-settings> diff --git a/services/core/java/com/android/server/incident/OWNERS b/services/core/java/com/android/server/incident/OWNERS new file mode 100644 index 000000000000..f76611555dbb --- /dev/null +++ b/services/core/java/com/android/server/incident/OWNERS @@ -0,0 +1 @@ +include /cmds/incidentd/OWNERS diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 42aad7d7ad5c..46ccf1e18802 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -51,6 +51,7 @@ import android.hardware.input.TouchCalibration; import android.media.AudioManager; import android.os.Binder; import android.os.Bundle; +import android.os.CombinedVibrationEffect; import android.os.Environment; import android.os.Handler; import android.os.IBinder; @@ -203,7 +204,12 @@ public class InputManagerService extends IInputManager.Stub private int mNextVibratorTokenValue; // State for lid switch + // Lock for the lid switch state. Held when triggering callbacks to guarantee lid switch events + // are delivered in order. For ex, when a new lid switch callback is registered the lock is held + // while the callback is processing the initial lid switch event which guarantees that any + // events that occur at the same time are delivered after the callback has returned. private final Object mLidSwitchLock = new Object(); + @GuardedBy("mLidSwitchLock") private List<LidSwitchCallback> mLidSwitchCallbacks = new ArrayList<>(); // State for the currently installed input filter. @@ -264,7 +270,11 @@ public class InputManagerService extends IInputManager.Stub private static native void nativeReloadCalibration(long ptr); private static native void nativeVibrate(long ptr, int deviceId, long[] pattern, int[] amplitudes, int repeat, int token); + private static native void nativeVibrateCombined(long ptr, int deviceId, long[] pattern, + SparseArray<int[]> amplitudes, int repeat, int token); private static native void nativeCancelVibrate(long ptr, int deviceId, int token); + private static native boolean nativeIsVibrating(long ptr, int deviceId); + private static native int[] nativeGetVibratorIds(long ptr, int deviceId); private static native void nativeReloadKeyboardLayouts(long ptr); private static native void nativeReloadDeviceAliases(long ptr); private static native String nativeDump(long ptr); @@ -343,9 +353,6 @@ public class InputManagerService extends IInputManager.Stub public static final int SW_CAMERA_LENS_COVER_BIT = 1 << SW_CAMERA_LENS_COVER; public static final int SW_MUTE_DEVICE_BIT = 1 << SW_MUTE_DEVICE; - /** Indicates an open state for the lid switch. */ - public static final int SW_STATE_LID_OPEN = 0; - /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */ final boolean mUseDevInputEventForAudioJack; @@ -381,13 +388,18 @@ public class InputManagerService extends IInputManager.Stub } void registerLidSwitchCallbackInternal(@NonNull LidSwitchCallback callback) { - boolean lidOpen; synchronized (mLidSwitchLock) { mLidSwitchCallbacks.add(callback); - lidOpen = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID) - == SW_STATE_LID_OPEN; + + // Skip triggering the initial callback if the system is not yet ready as the switch + // state will be reported as KEY_STATE_UNKNOWN. The callback will be triggered in + // systemRunning(). + if (mSystemReady) { + boolean lidOpen = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID) + == KEY_STATE_UP; + callback.notifyLidSwitchChanged(0 /* whenNanos */, lidOpen); + } } - callback.notifyLidSwitchChanged(0 /* whenNanos */, lidOpen); } void unregisterLidSwitchCallbackInternal(@NonNull LidSwitchCallback callback) { @@ -435,7 +447,18 @@ public class InputManagerService extends IInputManager.Stub } mNotificationManager = (NotificationManager)mContext.getSystemService( Context.NOTIFICATION_SERVICE); - mSystemReady = true; + + synchronized (mLidSwitchLock) { + mSystemReady = true; + + // Send the initial lid switch state to any callback registered before the system was + // ready. + int switchState = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID); + for (int i = 0; i < mLidSwitchCallbacks.size(); i++) { + LidSwitchCallback callback = mLidSwitchCallbacks.get(i); + callback.notifyLidSwitchChanged(0 /* whenNanos */, switchState == KEY_STATE_UP); + } + } IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); @@ -1801,43 +1824,57 @@ public class InputManagerService extends IInputManager.Stub return result; } - // Binder call - @Override - public void vibrate(int deviceId, VibrationEffect effect, IBinder token) { - long[] pattern; - int[] amplitudes; - int repeat; - if (effect instanceof VibrationEffect.OneShot) { - VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) effect; - pattern = new long[] { 0, oneShot.getDuration() }; - int amplitude = oneShot.getAmplitude(); - // android framework uses DEFAULT_AMPLITUDE to signal that the vibration - // should use some built-in default value, denoted here as DEFAULT_VIBRATION_MAGNITUDE - if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) { - amplitude = DEFAULT_VIBRATION_MAGNITUDE; - } - amplitudes = new int[] { 0, amplitude }; - repeat = -1; - } else if (effect instanceof VibrationEffect.Waveform) { - VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) effect; - pattern = waveform.getTimings(); - amplitudes = waveform.getAmplitudes(); - for (int i = 0; i < amplitudes.length; i++) { - if (amplitudes[i] == VibrationEffect.DEFAULT_AMPLITUDE) { - amplitudes[i] = DEFAULT_VIBRATION_MAGNITUDE; - } - } - repeat = waveform.getRepeatIndex(); - } else { - // TODO: Add support for prebaked effects - Log.w(TAG, "Pre-baked effects aren't supported on input devices"); - return; + private static class VibrationInfo { + private long[] mPattern = new long[0]; + private int[] mAmplitudes = new int[0]; + private int mRepeat = -1; + + public long[] getPattern() { + return mPattern; + } + + public int[] getAmplitudes() { + return mAmplitudes; } - if (repeat >= pattern.length) { - throw new ArrayIndexOutOfBoundsException(); + public int getRepeatIndex() { + return mRepeat; + } + + VibrationInfo(VibrationEffect effect) { + if (effect instanceof VibrationEffect.OneShot) { + VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) effect; + mPattern = new long[] { 0, oneShot.getDuration() }; + int amplitude = oneShot.getAmplitude(); + // android framework uses DEFAULT_AMPLITUDE to signal that the vibration + // should use some built-in default value, denoted here as + // DEFAULT_VIBRATION_MAGNITUDE + if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) { + amplitude = DEFAULT_VIBRATION_MAGNITUDE; + } + mAmplitudes = new int[] { 0, amplitude }; + mRepeat = -1; + } else if (effect instanceof VibrationEffect.Waveform) { + VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) effect; + mPattern = waveform.getTimings(); + mAmplitudes = waveform.getAmplitudes(); + for (int i = 0; i < mAmplitudes.length; i++) { + if (mAmplitudes[i] == VibrationEffect.DEFAULT_AMPLITUDE) { + mAmplitudes[i] = DEFAULT_VIBRATION_MAGNITUDE; + } + } + mRepeat = waveform.getRepeatIndex(); + if (mRepeat >= mPattern.length) { + throw new ArrayIndexOutOfBoundsException(); + } + } else { + // TODO: Add support for prebaked effects + Slog.w(TAG, "Pre-baked effects aren't supported on input devices"); + } } + } + private VibratorToken getVibratorToken(int deviceId, IBinder token) { VibratorToken v; synchronized (mVibratorLock) { v = mVibratorTokens.get(token); @@ -1852,9 +1889,70 @@ public class InputManagerService extends IInputManager.Stub mVibratorTokens.put(token, v); } } + return v; + } + + // Binder call + @Override + public void vibrate(int deviceId, VibrationEffect effect, IBinder token) { + VibrationInfo info = new VibrationInfo(effect); + VibratorToken v = getVibratorToken(deviceId, token); + synchronized (v) { + v.mVibrating = true; + nativeVibrate(mPtr, deviceId, info.getPattern(), info.getAmplitudes(), + info.getRepeatIndex(), v.mTokenValue); + } + } + + // Binder call + @Override + public int[] getVibratorIds(int deviceId) { + return nativeGetVibratorIds(mPtr, deviceId); + } + + // Binder call + @Override + public boolean isVibrating(int deviceId) { + return nativeIsVibrating(mPtr, deviceId); + } + + // Binder call + @Override + public void vibrateCombined(int deviceId, CombinedVibrationEffect effect, IBinder token) { + VibratorToken v = getVibratorToken(deviceId, token); synchronized (v) { + if (!(effect instanceof CombinedVibrationEffect.Mono) + && !(effect instanceof CombinedVibrationEffect.Stereo)) { + Slog.e(TAG, "Only Mono and Stereo effects are supported"); + return; + } + v.mVibrating = true; - nativeVibrate(mPtr, deviceId, pattern, amplitudes, repeat, v.mTokenValue); + if (effect instanceof CombinedVibrationEffect.Mono) { + CombinedVibrationEffect.Mono mono = (CombinedVibrationEffect.Mono) effect; + VibrationInfo info = new VibrationInfo(mono.getEffect()); + nativeVibrate(mPtr, deviceId, info.getPattern(), info.getAmplitudes(), + info.getRepeatIndex(), v.mTokenValue); + } else if (effect instanceof CombinedVibrationEffect.Stereo) { + CombinedVibrationEffect.Stereo stereo = (CombinedVibrationEffect.Stereo) effect; + SparseArray<VibrationEffect> effects = stereo.getEffects(); + long[] pattern = new long[0]; + int repeat = Integer.MIN_VALUE; + SparseArray<int[]> amplitudes = new SparseArray<int[]>(effects.size()); + for (int i = 0; i < effects.size(); i++) { + VibrationInfo info = new VibrationInfo(effects.valueAt(i)); + // Pattern of all effects should be same + if (pattern.length == 0) { + pattern = info.getPattern(); + } + if (repeat == Integer.MIN_VALUE) { + repeat = info.getRepeatIndex(); + } + amplitudes.put(effects.keyAt(i), info.getAmplitudes()); + } + nativeVibrateCombined(mPtr, deviceId, pattern, amplitudes, repeat, + v.mTokenValue); + } } } @@ -2045,14 +2143,13 @@ public class InputManagerService extends IInputManager.Stub if ((switchMask & SW_LID_BIT) != 0) { final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0); - - ArrayList<LidSwitchCallback> callbacksCopy; synchronized (mLidSwitchLock) { - callbacksCopy = new ArrayList<>(mLidSwitchCallbacks); - } - for (int i = 0; i < callbacksCopy.size(); i++) { - LidSwitchCallback callbacks = callbacksCopy.get(i); - callbacks.notifyLidSwitchChanged(whenNanos, lidOpen); + if (mSystemReady) { + for (int i = 0; i < mLidSwitchCallbacks.size(); i++) { + LidSwitchCallback callbacks = mLidSwitchCallbacks.get(i); + callbacks.notifyLidSwitchChanged(whenNanos, lidOpen); + } + } } } diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java index c3a10c7a4f8a..3854f8c8ff76 100644 --- a/services/core/java/com/android/server/location/LocationManagerService.java +++ b/services/core/java/com/android/server/location/LocationManagerService.java @@ -57,6 +57,7 @@ import android.location.IGpsGeofenceHardware; import android.location.ILocationCallback; import android.location.ILocationListener; import android.location.ILocationManager; +import android.location.LastLocationRequest; import android.location.Location; import android.location.LocationManager; import android.location.LocationManagerInternal; @@ -588,6 +589,30 @@ public class LocationManagerService extends ILocationManager.Stub { new String[0]); } + @Nullable + @Override + public ICancellationSignal getCurrentLocation(String provider, LocationRequest request, + ILocationCallback consumer, String packageName, String attributionTag, + String listenerId) { + CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag, + listenerId); + int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(), + identity.getPid()); + LocationPermissions.enforceLocationPermission(identity.getUid(), permissionLevel, + PERMISSION_COARSE); + + // clients in the system process must have an attribution tag set + Preconditions.checkState(identity.getPid() != Process.myPid() || attributionTag != null); + + request = validateLocationRequest(request, identity); + + LocationProviderManager manager = getLocationProviderManager(provider); + Preconditions.checkArgument(manager != null, + "provider \"" + provider + "\" does not exist"); + + return manager.getCurrentLocation(request, identity, permissionLevel, consumer); + } + @Override public void registerLocationListener(String provider, LocationRequest request, ILocationListener listener, String packageName, @Nullable String attributionTag, @@ -741,7 +766,8 @@ public class LocationManagerService extends ILocationManager.Stub { } @Override - public Location getLastLocation(String provider, String packageName, String attributionTag) { + public Location getLastLocation(String provider, LastLocationRequest request, + String packageName, String attributionTag) { CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag); int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(), identity.getPid()); @@ -751,36 +777,29 @@ public class LocationManagerService extends ILocationManager.Stub { // clients in the system process must have an attribution tag set Preconditions.checkArgument(identity.getPid() != Process.myPid() || attributionTag != null); + request = validateLastLocationRequest(request); + LocationProviderManager manager = getLocationProviderManager(provider); if (manager == null) { return null; } - return manager.getLastLocation(identity, permissionLevel, false); + return manager.getLastLocation(request, identity, permissionLevel); } - @Nullable - @Override - public ICancellationSignal getCurrentLocation(String provider, LocationRequest request, - ILocationCallback consumer, String packageName, String attributionTag, - String listenerId) { - CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag, - listenerId); - int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(), - identity.getPid()); - LocationPermissions.enforceLocationPermission(identity.getUid(), permissionLevel, - PERMISSION_COARSE); - - // clients in the system process must have an attribution tag set - Preconditions.checkState(identity.getPid() != Process.myPid() || attributionTag != null); - - request = validateLocationRequest(request, identity); - - LocationProviderManager manager = getLocationProviderManager(provider); - Preconditions.checkArgument(manager != null, - "provider \"" + provider + "\" does not exist"); + private LastLocationRequest validateLastLocationRequest(LastLocationRequest request) { + if (request.isHiddenFromAppOps()) { + mContext.enforceCallingOrSelfPermission( + permission.UPDATE_APP_OPS_STATS, + "hiding from app ops requires " + permission.UPDATE_APP_OPS_STATS); + } + if (request.isLocationSettingsIgnored()) { + mContext.enforceCallingOrSelfPermission( + permission.WRITE_SECURE_SETTINGS, + "ignoring location settings requires " + permission.WRITE_SECURE_SETTINGS); + } - return manager.getCurrentLocation(request, identity, permissionLevel, consumer); + return request; } @Override diff --git a/services/core/java/com/android/server/location/gnss/GnssPowerStats.java b/services/core/java/com/android/server/location/gnss/GnssPowerStats.java index 70ab3c647a97..b924d1fd98b2 100644 --- a/services/core/java/com/android/server/location/gnss/GnssPowerStats.java +++ b/services/core/java/com/android/server/location/gnss/GnssPowerStats.java @@ -16,8 +16,8 @@ package com.android.server.location.gnss; -import static android.hardware.gnss.IGnss.ELAPSED_REALTIME_HAS_TIMESTAMP_NS; -import static android.hardware.gnss.IGnss.ELAPSED_REALTIME_HAS_TIME_UNCERTAINTY_NS; +import static android.hardware.gnss.ElapsedRealtime.HAS_TIMESTAMP_NS; +import static android.hardware.gnss.ElapsedRealtime.HAS_TIME_UNCERTAINTY_NS; import com.android.internal.util.Preconditions; @@ -57,12 +57,12 @@ class GnssPowerStats { /** Returns true if {@link #getElapsedRealtimeNanos()} is available. */ public boolean hasElapsedRealtimeNanos() { - return (mElapsedRealtimeFlags & ELAPSED_REALTIME_HAS_TIMESTAMP_NS) != 0; + return (mElapsedRealtimeFlags & HAS_TIMESTAMP_NS) != 0; } /** Returns true if {@link #getElapsedRealtimeUncertaintyNanos()} is available. */ public boolean hasElapsedRealtimeUncertaintyNanos() { - return (mElapsedRealtimeFlags & ELAPSED_REALTIME_HAS_TIME_UNCERTAINTY_NS) != 0; + return (mElapsedRealtimeFlags & HAS_TIME_UNCERTAINTY_NS) != 0; } /** diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java index c5d7f2c033dd..2fe8bcc9140a 100644 --- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java +++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java @@ -49,6 +49,7 @@ import android.content.Intent; import android.location.Criteria; import android.location.ILocationCallback; import android.location.ILocationListener; +import android.location.LastLocationRequest; import android.location.Location; import android.location.LocationManager; import android.location.LocationManagerInternal; @@ -1467,9 +1468,9 @@ public class LocationProviderManager extends } } - public @Nullable Location getLastLocation(CallerIdentity identity, - @PermissionLevel int permissionLevel, boolean ignoreLocationSettings) { - if (!isActive(ignoreLocationSettings, identity)) { + public @Nullable Location getLastLocation(LastLocationRequest request, + CallerIdentity identity, @PermissionLevel int permissionLevel) { + if (!isActive(request.isLocationSettingsIgnored(), identity)) { return null; } @@ -1483,7 +1484,7 @@ public class LocationProviderManager extends getLastLocationUnsafe( identity.getUserId(), permissionLevel, - ignoreLocationSettings, + request.isLocationSettingsIgnored(), Long.MAX_VALUE), permissionLevel); diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java index c4581c88f49e..834cf0536865 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java @@ -16,8 +16,6 @@ package com.android.server.locksettings; -import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE; - import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN; @@ -271,15 +269,17 @@ class LockSettingsShellCommand extends ShellCommand { private boolean isNewCredentialSufficient(LockscreenCredential credential) { final PasswordMetrics requiredMetrics = mLockPatternUtils.getRequestedPasswordMetrics(mCurrentUserId); + final int requiredComplexity = + mLockPatternUtils.getRequestedPasswordComplexity(mCurrentUserId); final List<PasswordValidationError> errors; if (credential.isPassword() || credential.isPin()) { - errors = PasswordMetrics.validatePassword(requiredMetrics, PASSWORD_COMPLEXITY_NONE, + errors = PasswordMetrics.validatePassword(requiredMetrics, requiredComplexity, credential.isPin(), credential.getCredential()); } else { PasswordMetrics metrics = new PasswordMetrics( credential.isPattern() ? CREDENTIAL_TYPE_PATTERN : CREDENTIAL_TYPE_NONE); errors = PasswordMetrics.validatePasswordMetrics( - requiredMetrics, PASSWORD_COMPLEXITY_NONE, false /* isPin */, metrics); + requiredMetrics, requiredComplexity, false /* isPin */, metrics); } if (!errors.isEmpty()) { getOutPrintWriter().println( diff --git a/services/core/java/com/android/server/locksettings/OWNERS b/services/core/java/com/android/server/locksettings/OWNERS new file mode 100644 index 000000000000..dad6e39be47f --- /dev/null +++ b/services/core/java/com/android/server/locksettings/OWNERS @@ -0,0 +1,2 @@ +jaggies@google.com +kchyn@google.com diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java index f0bf5c0975f2..9c5abd4706a3 100644 --- a/services/core/java/com/android/server/net/IpConfigStore.java +++ b/services/core/java/com/android/server/net/IpConfigStore.java @@ -16,11 +16,11 @@ package com.android.server.net; +import android.net.InetAddresses; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; import android.net.LinkAddress; -import android.net.NetworkUtils; import android.net.ProxyInfo; import android.net.RouteInfo; import android.net.StaticIpConfiguration; @@ -284,8 +284,10 @@ public class IpConfigStore { } else if (key.equals(IP_ASSIGNMENT_KEY)) { ipAssignment = IpAssignment.valueOf(in.readUTF()); } else if (key.equals(LINK_ADDRESS_KEY)) { - LinkAddress linkAddr = new LinkAddress( - NetworkUtils.numericToInetAddress(in.readUTF()), in.readInt()); + LinkAddress linkAddr = + new LinkAddress( + InetAddresses.parseNumericAddress(in.readUTF()), + in.readInt()); if (linkAddr.getAddress() instanceof Inet4Address && staticIpConfiguration.ipAddress == null) { staticIpConfiguration.ipAddress = linkAddr; @@ -297,7 +299,7 @@ public class IpConfigStore { InetAddress gateway = null; if (version == 1) { // only supported default gateways - leave the dest/prefix empty - gateway = NetworkUtils.numericToInetAddress(in.readUTF()); + gateway = InetAddresses.parseNumericAddress(in.readUTF()); if (staticIpConfiguration.gateway == null) { staticIpConfiguration.gateway = gateway; } else { @@ -305,12 +307,13 @@ public class IpConfigStore { } } else { if (in.readInt() == 1) { - dest = new LinkAddress( - NetworkUtils.numericToInetAddress(in.readUTF()), - in.readInt()); + dest = + new LinkAddress( + InetAddresses.parseNumericAddress(in.readUTF()), + in.readInt()); } if (in.readInt() == 1) { - gateway = NetworkUtils.numericToInetAddress(in.readUTF()); + gateway = InetAddresses.parseNumericAddress(in.readUTF()); } RouteInfo route = new RouteInfo(dest, gateway); if (route.isIPv4Default() && @@ -322,7 +325,7 @@ public class IpConfigStore { } } else if (key.equals(DNS_KEY)) { staticIpConfiguration.dnsServers.add( - NetworkUtils.numericToInetAddress(in.readUTF())); + InetAddresses.parseNumericAddress(in.readUTF())); } else if (key.equals(PROXY_SETTINGS_KEY)) { proxySettings = ProxySettings.valueOf(in.readUTF()); } else if (key.equals(PROXY_HOST_KEY)) { diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index a44ddcb03c16..5f8b31abb23d 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -230,7 +230,6 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.DumpUtils; -import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.StatLogger; import com.android.internal.util.XmlUtils; @@ -243,9 +242,7 @@ import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener; import libcore.io.IoUtils; -import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; import java.io.File; import java.io.FileDescriptor; @@ -256,7 +253,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.nio.charset.StandardCharsets; import java.time.Clock; import java.time.Instant; import java.time.ZoneId; @@ -271,6 +267,7 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.function.IntConsumer; /** * Service that maintains low-level network policy rules, using @@ -4034,7 +4031,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { try { updateRulesForDeviceIdleUL(); updateRulesForPowerSaveUL(); - updateRulesForAllAppsUL(TYPE_RESTRICT_POWER); + forEachUid("updateRulesForRestrictPower", + uid -> updateRulesForPowerRestrictionsUL(uid)); } finally { Trace.traceEnd(Trace.TRACE_TAG_NETWORK); } @@ -4044,31 +4042,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private void updateRulesForRestrictBackgroundUL() { Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForRestrictBackgroundUL"); try { - updateRulesForAllAppsUL(TYPE_RESTRICT_BACKGROUND); + forEachUid("updateRulesForRestrictBackground", + uid -> updateRulesForDataUsageRestrictionsUL(uid)); } finally { Trace.traceEnd(Trace.TRACE_TAG_NETWORK); } } - private static final int TYPE_RESTRICT_BACKGROUND = 1; - private static final int TYPE_RESTRICT_POWER = 2; - @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = false, value = { - TYPE_RESTRICT_BACKGROUND, - TYPE_RESTRICT_POWER, - }) - public @interface RestrictType { - } - - // TODO: refactor / consolidate all those updateXyz methods, there are way too many of them... - @GuardedBy("mUidRulesFirstLock") - private void updateRulesForAllAppsUL(@RestrictType int type) { + private void forEachUid(String tag, IntConsumer consumer) { if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) { - Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForRestrictPowerUL-" + type); + Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "forEachUid-" + tag); } try { // update rules for all installed applications - final PackageManager pm = mContext.getPackageManager(); final List<UserInfo> users; final List<ApplicationInfo> apps; @@ -4096,16 +4082,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { for (int j = 0; j < appsSize; j++) { final ApplicationInfo app = apps.get(j); final int uid = UserHandle.getUid(user.id, app.uid); - switch (type) { - case TYPE_RESTRICT_BACKGROUND: - updateRulesForDataUsageRestrictionsUL(uid); - break; - case TYPE_RESTRICT_POWER: - updateRulesForPowerRestrictionsUL(uid); - break; - default: - Slog.w(TAG, "Invalid type for updateRulesForAllApps: " + type); - } + consumer.accept(uid); } } } finally { diff --git a/services/core/java/com/android/server/net/OWNERS b/services/core/java/com/android/server/net/OWNERS index 28ae6a417bd3..d5c7618199fe 100644 --- a/services/core/java/com/android/server/net/OWNERS +++ b/services/core/java/com/android/server/net/OWNERS @@ -2,7 +2,7 @@ set noparent codewiz@google.com jchalard@google.com -jsharkey@android.com +jsharkey@google.com junyulai@google.com lorenzo@google.com reminv@google.com diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java index 8200ca0523be..769b781b1ae9 100644 --- a/services/core/java/com/android/server/notification/ConditionProviders.java +++ b/services/core/java/com/android/server/notification/ConditionProviders.java @@ -123,7 +123,7 @@ public class ConditionProviders extends ManagedServices { final Config c = new Config(); c.caption = "condition provider"; c.serviceInterface = ConditionProviderService.SERVICE_INTERFACE; - c.secureSettingName = Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES; + c.secureSettingName = null; c.xmlTag = TAG_ENABLED_DND_APPS; c.secondarySettingName = Settings.Secure.ENABLED_NOTIFICATION_LISTENERS; c.bindPermission = android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE; diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index a7ee27286a24..54e9b37be64a 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -437,9 +437,15 @@ abstract public class ManagedServices { } } } - Settings.Secure.putStringForUser( - mContext.getContentResolver(), element, value, userId); - loadAllowedComponentsFromSettings(); + if (shouldReflectToSettings()) { + Settings.Secure.putStringForUser( + mContext.getContentResolver(), element, value, userId); + } + + for (UserInfo user : mUm.getUsers()) { + addApprovedList(value, user.id, mConfig.secureSettingName.equals(element)); + } + Slog.d(TAG, "Done loading approved values from settings"); rebindServices(false, userId); } } @@ -498,10 +504,13 @@ abstract public class ManagedServices { out.endTag(null, TAG_MANAGED_SERVICES); if (!forBackup && isPrimary) { - // Also write values to settings, for observers who haven't migrated yet - Settings.Secure.putStringForUser(mContext.getContentResolver(), - getConfig().secureSettingName, allowedItems, - approvedUserId); + if (shouldReflectToSettings()) { + // Also write values to settings, for observers who haven't + // migrated yet + Settings.Secure.putStringForUser(mContext.getContentResolver(), + getConfig().secureSettingName, allowedItems, + approvedUserId); + } } } @@ -516,6 +525,13 @@ abstract public class ManagedServices { } /** + * Returns whether the approved list of services should also be written to the Settings db + */ + protected boolean shouldReflectToSettings() { + return false; + } + + /** * Writes extra xml attributes to {@link #TAG_MANAGED_SERVICES} tag. */ protected void writeExtraAttributes(TypedXmlSerializer out, int userId) throws IOException {} @@ -530,8 +546,20 @@ abstract public class ManagedServices { */ protected void readExtraTag(String tag, TypedXmlPullParser parser) throws IOException {} - protected void migrateToXml() { - loadAllowedComponentsFromSettings(); + protected final void migrateToXml() { + for (UserInfo user : mUm.getUsers()) { + final ContentResolver cr = mContext.getContentResolver(); + addApprovedList(Settings.Secure.getStringForUser( + cr, + getConfig().secureSettingName, + user.id), user.id, true); + if (!TextUtils.isEmpty(getConfig().secondarySettingName)) { + addApprovedList(Settings.Secure.getStringForUser( + cr, + getConfig().secondarySettingName, + user.id), user.id, false); + } + } } void readDefaults(TypedXmlPullParser parser) { @@ -638,23 +666,6 @@ abstract public class ManagedServices { protected abstract String getRequiredPermission(); - private void loadAllowedComponentsFromSettings() { - for (UserInfo user : mUm.getUsers()) { - final ContentResolver cr = mContext.getContentResolver(); - addApprovedList(Settings.Secure.getStringForUser( - cr, - getConfig().secureSettingName, - user.id), user.id, true); - if (!TextUtils.isEmpty(getConfig().secondarySettingName)) { - addApprovedList(Settings.Secure.getStringForUser( - cr, - getConfig().secondarySettingName, - user.id), user.id, false); - } - } - Slog.d(TAG, "Done loading approved values from settings"); - } - protected void addApprovedList(String approved, int userId, boolean isPrimary) { addApprovedList(approved, userId, isPrimary, approved); } diff --git a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java index 7257f522221f..b9984a5c24ee 100644 --- a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java +++ b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java @@ -293,7 +293,7 @@ public class NotificationHistoryDatabase { .appendPath(file.getAbsolutePath()).build()) .addFlags(Intent.FLAG_RECEIVER_FOREGROUND) .putExtra(EXTRA_KEY, file.getAbsolutePath()), - PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, deletionTime, pi); } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index eb7ef2bbeaf2..525fca073ede 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -242,7 +242,6 @@ import android.widget.Toast; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.compat.IPlatformCompat; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.logging.InstanceId; import com.android.internal.logging.InstanceIdSequence; @@ -468,7 +467,6 @@ public class NotificationManagerService extends SystemService { private UriGrantsManagerInternal mUgmInternal; private RoleObserver mRoleObserver; private UserManager mUm; - private IPlatformCompat mPlatformCompat; private ShortcutHelper mShortcutHelper; final IBinder mForegroundToken = new Binder(); @@ -1987,8 +1985,6 @@ public class NotificationManagerService extends SystemService { mDeviceIdleManager = getContext().getSystemService(DeviceIdleManager.class); mDpm = dpm; mUm = userManager; - mPlatformCompat = IPlatformCompat.Stub.asInterface( - ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); mUiHandler = new Handler(UiThread.get().getLooper()); String[] extractorNames; @@ -2886,16 +2882,16 @@ public class NotificationManagerService extends SystemService { return userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId; } - private ToastRecord getToastRecord(int uid, int pid, String packageName, IBinder token, - @Nullable CharSequence text, @Nullable ITransientNotification callback, int duration, - Binder windowToken, int displayId, + private ToastRecord getToastRecord(int uid, int pid, String packageName, boolean isSystemToast, + IBinder token, @Nullable CharSequence text, @Nullable ITransientNotification callback, + int duration, Binder windowToken, int displayId, @Nullable ITransientNotificationCallback textCallback) { if (callback == null) { - return new TextToastRecord(this, mStatusBar, uid, pid, packageName, token, text, - duration, windowToken, displayId, textCallback); + return new TextToastRecord(this, mStatusBar, uid, pid, packageName, + isSystemToast, token, text, duration, windowToken, displayId, textCallback); } else { - return new CustomToastRecord(this, uid, pid, packageName, token, callback, duration, - windowToken, displayId); + return new CustomToastRecord(this, uid, pid, packageName, + isSystemToast, token, callback, duration, windowToken, displayId); } } @@ -2966,31 +2962,10 @@ public class NotificationManagerService extends SystemService { } boolean isAppRenderedToast = (callback != null); - if (isAppRenderedToast && !isSystemToast && !isPackageInForegroundForToast(pkg, - callingUid)) { - boolean block; - final long id = Binder.clearCallingIdentity(); - try { - // CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK is gated on targetSdk, so block will be - // false for apps with targetSdk < R. For apps with targetSdk R+, text toasts - // are not app-rendered, so isAppRenderedToast == true means it's a custom - // toast. - block = mPlatformCompat.isChangeEnabledByPackageName( - CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK, pkg, - callingUser.getIdentifier()); - } catch (RemoteException e) { - // Shouldn't happen have since it's a local local - Slog.e(TAG, "Unexpected exception while checking block background custom toasts" - + " change", e); - block = false; - } finally { - Binder.restoreCallingIdentity(id); - } - if (block) { - Slog.w(TAG, "Blocking custom toast from package " + pkg - + " due to package not in the foreground"); - return; - } + if (blockToast(callingUid, isSystemToast, isAppRenderedToast)) { + Slog.w(TAG, "Blocking custom toast from package " + pkg + + " due to package not in the foreground at time the toast was posted"); + return; } synchronized (mToastQueue) { @@ -3023,8 +2998,8 @@ public class NotificationManagerService extends SystemService { Binder windowToken = new Binder(); mWindowManagerInternal.addWindowToken(windowToken, TYPE_TOAST, displayId); - record = getToastRecord(callingUid, callingPid, pkg, token, text, callback, - duration, windowToken, displayId, textCallback); + record = getToastRecord(callingUid, callingPid, pkg, isSystemToast, token, + text, callback, duration, windowToken, displayId, textCallback); mToastQueue.add(record); index = mToastQueue.size() - 1; keepProcessAliveForToastIfNeededLocked(callingPid); @@ -3042,28 +3017,6 @@ public class NotificationManagerService extends SystemService { } } - /** - * Implementation note: Our definition of foreground for toasts is an implementation matter - * and should strike a balance between functionality and anti-abuse effectiveness. We - * currently worry about the following cases: - * <ol> - * <li>App with fullscreen activity: Allow toasts - * <li>App behind translucent activity from other app: Block toasts - * <li>App in multi-window: Allow toasts - * <li>App with expanded bubble: Allow toasts - * <li>App posting toasts on onCreate(), onStart(), onResume(): Allow toasts - * <li>App posting toasts on onPause(), onStop(), onDestroy(): Block toasts - * </ol> - * Checking if the UID has any resumed activities satisfy use-cases above. - * - * <p>Checking if {@code mActivityManager.getUidImportance(callingUid) == - * IMPORTANCE_FOREGROUND} does not work because it considers the app in foreground if it has - * any visible activities, failing case 2 in list above. - */ - private boolean isPackageInForegroundForToast(String pkg, int callingUid) { - return mAtm.hasResumedActivity(callingUid); - } - @Override public void cancelToast(String pkg, IBinder token) { Slog.i(TAG, "cancelToast pkg=" + pkg + " token=" + token); @@ -7388,17 +7341,16 @@ public class NotificationManagerService extends SystemService { CompatChanges.isChangeEnabled(RATE_LIMIT_TOASTS, record.uid); boolean isWithinQuota = mToastRateLimiter.isWithinQuota(userId, record.pkg, TOAST_QUOTA_TAG); - if ((!rateLimitingEnabled || isWithinQuota) && record.show()) { + + if (tryShowToast(record, rateLimitingEnabled, isWithinQuota)) { scheduleDurationReachedLocked(record); mIsCurrentToastShown = true; if (rateLimitingEnabled) { mToastRateLimiter.noteEvent(userId, record.pkg, TOAST_QUOTA_TAG); } return; - } else if (rateLimitingEnabled && !isWithinQuota) { - Slog.w(TAG, "Package " + record.pkg + " is above allowed toast quota, the " - + "following toast was blocked and discarded: " + record); } + int index = mToastQueue.indexOf(record); if (index >= 0) { mToastQueue.remove(index); @@ -7407,6 +7359,22 @@ public class NotificationManagerService extends SystemService { } } + /** Returns true if it successfully showed the toast. */ + private boolean tryShowToast(ToastRecord record, boolean rateLimitingEnabled, + boolean isWithinQuota) { + if (rateLimitingEnabled && !isWithinQuota) { + Slog.w(TAG, "Package " + record.pkg + " is above allowed toast quota, the " + + "following toast was blocked and discarded: " + record); + return false; + } + if (blockToast(record.uid, record.isSystemToast, record.isAppRendered())) { + Slog.w(TAG, "Blocking custom toast from package " + record.pkg + + " due to package not in the foreground at the time of showing the toast"); + return false; + } + return record.show(); + } + @GuardedBy("mToastQueue") void cancelToastLocked(int index) { ToastRecord record = mToastQueue.get(index); @@ -7526,6 +7494,44 @@ public class NotificationManagerService extends SystemService { } } + /** + * Implementation note: Our definition of foreground for toasts is an implementation matter + * and should strike a balance between functionality and anti-abuse effectiveness. We + * currently worry about the following cases: + * <ol> + * <li>App with fullscreen activity: Allow toasts + * <li>App behind translucent activity from other app: Block toasts + * <li>App in multi-window: Allow toasts + * <li>App with expanded bubble: Allow toasts + * <li>App posting toasts on onCreate(), onStart(), onResume(): Allow toasts + * <li>App posting toasts on onPause(), onStop(), onDestroy(): Block toasts + * </ol> + * Checking if the UID has any resumed activities satisfy use-cases above. + * + * <p>Checking if {@code mActivityManager.getUidImportance(callingUid) == + * IMPORTANCE_FOREGROUND} does not work because it considers the app in foreground if it has + * any visible activities, failing case 2 in list above. + */ + private boolean isPackageInForegroundForToast(int callingUid) { + return mAtm.hasResumedActivity(callingUid); + } + + /** + * True if the toast should be blocked. It will return true if all of the following conditions + * apply: it's a custom toast, it's not a system toast, the package that sent the toast is in + * the background and CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK is enabled. + * + * CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK is gated on targetSdk, so it will return false for apps + * with targetSdk < R. For apps with targetSdk R+, text toasts are not app-rendered, so + * isAppRenderedToast == true means it's a custom toast. + */ + private boolean blockToast(int uid, boolean isSystemToast, boolean isAppRenderedToast) { + return isAppRenderedToast + && !isSystemToast + && !isPackageInForegroundForToast(uid) + && CompatChanges.isChangeEnabled(CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK, uid); + } + private void handleRankingReconsideration(Message message) { if (!(message.obj instanceof RankingReconsideration)) return; RankingReconsideration recon = (RankingReconsideration) message.obj; @@ -9180,7 +9186,16 @@ public class NotificationManagerService extends SystemService { @Override protected void readExtraAttributes(String tag, TypedXmlPullParser parser, int userId) throws IOException { - boolean userSet = parser.getAttributeBoolean(null, ATT_USER_SET, false); + // TODO: this logic looks broken, since it's trying to convert a + // list into a boolean; for now we preserve the old parsing behavior + // to avoid a performance regression, but someone should investigate + final String value = parser.getAttributeValue(null, ATT_USER_SET); + final boolean userSet; + if (TextUtils.isEmpty(value)) { + userSet = false; + } else { + userSet = Boolean.parseBoolean(value); + } setUserSet(userId, userSet); } @@ -9527,6 +9542,13 @@ public class NotificationManagerService extends SystemService { return null; } + @Override + protected boolean shouldReflectToSettings() { + // androidx has a public method that reads the approved set of listeners from + // Settings so we have to continue writing this list for this type of service + return true; + } + @GuardedBy("mNotificationLock") public void setOnNotificationPostedTrimLocked(ManagedServiceInfo info, int trim) { if (trim == TRIM_LIGHT) { diff --git a/services/core/java/com/android/server/notification/OWNERS b/services/core/java/com/android/server/notification/OWNERS index 5a19656b36a6..4dcb7995d8ae 100644 --- a/services/core/java/com/android/server/notification/OWNERS +++ b/services/core/java/com/android/server/notification/OWNERS @@ -1,4 +1,4 @@ -dsandler@android.com +dsandler@google.com juliacr@google.com beverlyt@google.com pixel@google.com diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java index 2122b9c19805..f078242a659f 100644 --- a/services/core/java/com/android/server/notification/SnoozeHelper.java +++ b/services/core/java/com/android/server/notification/SnoozeHelper.java @@ -469,7 +469,7 @@ public class SnoozeHelper { .addFlags(Intent.FLAG_RECEIVER_FOREGROUND) .putExtra(EXTRA_KEY, key) .putExtra(EXTRA_USER_ID, userId), - PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); } public void scheduleRepostsForPersistedNotifications(long currentTime) { diff --git a/services/core/java/com/android/server/notification/toast/CustomToastRecord.java b/services/core/java/com/android/server/notification/toast/CustomToastRecord.java index 17e0b39ea890..30378ac058c6 100644 --- a/services/core/java/com/android/server/notification/toast/CustomToastRecord.java +++ b/services/core/java/com/android/server/notification/toast/CustomToastRecord.java @@ -37,9 +37,10 @@ public class CustomToastRecord extends ToastRecord { public final ITransientNotification callback; public CustomToastRecord(NotificationManagerService notificationManager, int uid, int pid, - String packageName, IBinder token, ITransientNotification callback, int duration, - Binder windowToken, int displayId) { - super(notificationManager, uid, pid, packageName, token, duration, windowToken, displayId); + String packageName, boolean isSystemToast, IBinder token, + ITransientNotification callback, int duration, Binder windowToken, int displayId) { + super(notificationManager, uid, pid, packageName, isSystemToast, token, duration, + windowToken, displayId); this.callback = checkNotNull(callback); } @@ -78,10 +79,16 @@ public class CustomToastRecord extends ToastRecord { } @Override + public boolean isAppRendered() { + return true; + } + + @Override public String toString() { return "CustomToastRecord{" + Integer.toHexString(System.identityHashCode(this)) + " " + pid + ":" + pkg + "/" + UserHandle.formatUid(uid) + + " isSystemToast=" + isSystemToast + " token=" + token + " callback=" + callback + " duration=" + getDuration() diff --git a/services/core/java/com/android/server/notification/toast/TextToastRecord.java b/services/core/java/com/android/server/notification/toast/TextToastRecord.java index 544520edc7fc..7b36db2fe38c 100644 --- a/services/core/java/com/android/server/notification/toast/TextToastRecord.java +++ b/services/core/java/com/android/server/notification/toast/TextToastRecord.java @@ -43,9 +43,11 @@ public class TextToastRecord extends ToastRecord { public TextToastRecord(NotificationManagerService notificationManager, @Nullable StatusBarManagerInternal statusBarManager, int uid, int pid, - String packageName, IBinder token, CharSequence text, int duration, Binder windowToken, - int displayId, @Nullable ITransientNotificationCallback callback) { - super(notificationManager, uid, pid, packageName, token, duration, windowToken, displayId); + String packageName, boolean isSystemToast, IBinder token, CharSequence text, + int duration, Binder windowToken, int displayId, + @Nullable ITransientNotificationCallback callback) { + super(notificationManager, uid, pid, packageName, isSystemToast, token, duration, + windowToken, displayId); mStatusBar = statusBarManager; mCallback = callback; this.text = checkNotNull(text); @@ -73,10 +75,16 @@ public class TextToastRecord extends ToastRecord { } @Override + public boolean isAppRendered() { + return false; + } + + @Override public String toString() { return "TextToastRecord{" + Integer.toHexString(System.identityHashCode(this)) + " " + pid + ":" + pkg + "/" + UserHandle.formatUid(uid) + + " isSystemToast=" + isSystemToast + " token=" + token + " text=" + text + " duration=" + getDuration() diff --git a/services/core/java/com/android/server/notification/toast/ToastRecord.java b/services/core/java/com/android/server/notification/toast/ToastRecord.java index 33906ccd3cd1..1d5fc27c52c2 100644 --- a/services/core/java/com/android/server/notification/toast/ToastRecord.java +++ b/services/core/java/com/android/server/notification/toast/ToastRecord.java @@ -31,6 +31,7 @@ public abstract class ToastRecord { public final int uid; public final int pid; public final String pkg; + public final boolean isSystemToast; public final IBinder token; public final int displayId; public final Binder windowToken; @@ -38,11 +39,13 @@ public abstract class ToastRecord { private int mDuration; protected ToastRecord(NotificationManagerService notificationManager, int uid, int pid, - String pkg, IBinder token, int duration, Binder windowToken, int displayId) { + String pkg, boolean isSystemToast, IBinder token, int duration, Binder windowToken, + int displayId) { this.mNotificationManager = notificationManager; this.uid = uid; this.pid = pid; this.pkg = pkg; + this.isSystemToast = isSystemToast; this.token = token; this.windowToken = windowToken; this.displayId = displayId; @@ -95,4 +98,10 @@ public abstract class ToastRecord { // should override this method. return false; } + + /** + * Returns true if the app is responsible for rendering the toast, false otherwise (for example, + * if it's rendered by the system). + */ + public abstract boolean isAppRendered(); } diff --git a/services/core/java/com/android/server/om/OWNERS b/services/core/java/com/android/server/om/OWNERS new file mode 100644 index 000000000000..afb98d416762 --- /dev/null +++ b/services/core/java/com/android/server/om/OWNERS @@ -0,0 +1 @@ +include /core/java/android/content/om/OWNERS diff --git a/services/core/java/com/android/server/people/OWNERS b/services/core/java/com/android/server/people/OWNERS new file mode 100644 index 000000000000..3198a5e84307 --- /dev/null +++ b/services/core/java/com/android/server/people/OWNERS @@ -0,0 +1 @@ +include /services/people/OWNERS diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS index cca2b8394c63..7a2b7a62b7dd 100644 --- a/services/core/java/com/android/server/pm/OWNERS +++ b/services/core/java/com/android/server/pm/OWNERS @@ -1,12 +1,12 @@ -hackbod@android.com hackbod@google.com -jsharkey@android.com +hackbod@google.com +jsharkey@google.com jsharkey@google.com narayan@google.com patb@google.com -svetoslavganov@android.com svetoslavganov@google.com -toddke@android.com +svetoslavganov@google.com +toddke@google.com toddke@google.com # apex support @@ -30,9 +30,10 @@ per-file CrossProfileAppsServiceImpl.java = omakoto@google.com, yamasani@google. per-file CrossProfileAppsService.java = omakoto@google.com, yamasani@google.com per-file CrossProfileIntentFilter.java = omakoto@google.com, yamasani@google.com per-file CrossProfileIntentResolver.java = omakoto@google.com, yamasani@google.com +per-file RestrictionsSet.java = bookatz@google.com, omakoto@google.com, yamasani@google.com, rubinxu@google.com, sandness@google.com +per-file UserManagerInternal.java = bookatz@google.com, omakoto@google.com, yamasani@google.com per-file UserManagerService.java = bookatz@google.com, omakoto@google.com, yamasani@google.com per-file UserRestrictionsUtils.java = omakoto@google.com, rubinxu@google.com, sandness@google.com, yamasani@google.com -per-file RestrictionsSet.java = bookatz@google.com, omakoto@google.com, yamasani@google.com, rubinxu@google.com, sandness@google.com per-file UserSystemPackageInstaller.java = bookatz@google.com, omakoto@google.com, yamasani@google.com per-file UserTypeDetails.java = bookatz@google.com, omakoto@google.com, yamasani@google.com per-file UserTypeFactory.java = bookatz@google.com, omakoto@google.com, yamasani@google.com diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 4cee2e58d20e..9f8f6e4408f8 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -532,6 +532,20 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements + "to use a data loader"); } + // INSTALL_REASON_ROLLBACK allows an app to be rolled back without requiring the ROLLBACK + // capability; ensure if this is set as the install reason the app has one of the necessary + // signature permissions to perform the rollback. + if (params.installReason == PackageManager.INSTALL_REASON_ROLLBACK) { + if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_ROLLBACKS) + != PackageManager.PERMISSION_GRANTED && + mContext.checkCallingOrSelfPermission(Manifest.permission.TEST_MANAGE_ROLLBACKS) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException( + "INSTALL_REASON_ROLLBACK requires the MANAGE_ROLLBACKS permission or the " + + "TEST_MANAGE_ROLLBACKS permission"); + } + } + // App package name and label length is restricted so that really long strings aren't // written to disk. if (params.appPackageName != null @@ -686,11 +700,6 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } } - if (params.whitelistedRestrictedPermissions != null) { - mPermissionManager.retainHardAndSoftRestrictedPermissions( - params.whitelistedRestrictedPermissions); - } - final int sessionId; final PackageInstallerSession session; synchronized (mSessions) { diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 0aebe721b103..4ab12823dfb7 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -756,6 +756,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { info.mode = params.mode; info.installReason = params.installReason; + info.installScenario = params.installScenario; info.sizeBytes = params.sizeBytes; info.appPackageName = mPackageName != null ? mPackageName : params.appPackageName; if (includeIcon) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index a123f369a9ab..d14baf561f01 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -24,6 +24,7 @@ import static android.Manifest.permission.SET_HARMFUL_APP_WARNINGS; import static android.app.AppOpsManager.MODE_DEFAULT; import static android.app.AppOpsManager.MODE_IGNORED; import static android.content.Intent.ACTION_MAIN; +import static android.content.Intent.CATEGORY_BROWSABLE; import static android.content.Intent.CATEGORY_DEFAULT; import static android.content.Intent.CATEGORY_HOME; import static android.content.Intent.EXTRA_LONG_VERSION_CODE; @@ -238,6 +239,7 @@ import android.content.pm.VersionedPackage; import android.content.pm.dex.ArtManager; import android.content.pm.dex.DexMetadataHelper; import android.content.pm.dex.IArtManager; +import android.content.pm.parsing.ApkLiteParseUtils; import android.content.pm.parsing.ParsingPackageUtils; import android.content.pm.parsing.component.ParsedActivity; import android.content.pm.parsing.component.ParsedInstrumentation; @@ -248,6 +250,8 @@ import android.content.pm.parsing.component.ParsedPermissionGroup; import android.content.pm.parsing.component.ParsedProcess; import android.content.pm.parsing.component.ParsedProvider; import android.content.pm.parsing.component.ParsedService; +import android.content.pm.parsing.result.ParseResult; +import android.content.pm.parsing.result.ParseTypeImpl; import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.Bitmap; @@ -698,10 +702,15 @@ public class PackageManagerService extends IPackageManager.Stub public static final int REASON_FIRST_BOOT = 0; public static final int REASON_BOOT = 1; public static final int REASON_INSTALL = 2; - public static final int REASON_BACKGROUND_DEXOPT = 3; - public static final int REASON_AB_OTA = 4; - public static final int REASON_INACTIVE_PACKAGE_DOWNGRADE = 5; - public static final int REASON_SHARED = 6; + public static final int REASON_INSTALL_FAST = 3; + public static final int REASON_INSTALL_BULK = 4; + public static final int REASON_INSTALL_BULK_SECONDARY = 5; + public static final int REASON_INSTALL_BULK_DOWNGRADED = 6; + public static final int REASON_INSTALL_BULK_SECONDARY_DOWNGRADED = 7; + public static final int REASON_BACKGROUND_DEXOPT = 8; + public static final int REASON_AB_OTA = 9; + public static final int REASON_INACTIVE_PACKAGE_DOWNGRADE = 10; + public static final int REASON_SHARED = 11; public static final int REASON_LAST = REASON_SHARED; @@ -7998,6 +8007,13 @@ public class PackageManagerService extends IPackageManager.Stub Slog.i(TAG, " + always: " + info.activityInfo.packageName + " : linkgen=" + linkGeneration); } + + if (!intent.hasCategory(CATEGORY_BROWSABLE) + || !intent.hasCategory(CATEGORY_DEFAULT)) { + undefinedList.add(info); + continue; + } + // Use link-enabled generation as preferredOrder, i.e. // prefer newly-enabled over earlier-enabled. info.preferredOrder = linkGeneration; @@ -15308,6 +15324,7 @@ public class PackageManagerService extends IPackageManager.Stub final int autoRevokePermissionsMode; final PackageParser.SigningDetails signingDetails; final int installReason; + final int mInstallScenario; @Nullable MultiPackageInstallParams mParentInstallParams; final boolean forceQueryableOverride; final int mDataLoaderType; @@ -15316,7 +15333,7 @@ public class PackageManagerService extends IPackageManager.Stub InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer, int installFlags, InstallSource installSource, String volumeUuid, - UserHandle user, String packageAbiOverride) { + UserHandle user, String packageAbiOverride, PackageLite packageLite) { super(user); this.origin = origin; this.move = move; @@ -15331,10 +15348,11 @@ public class PackageManagerService extends IPackageManager.Stub this.autoRevokePermissionsMode = MODE_DEFAULT; this.signingDetails = PackageParser.SigningDetails.UNKNOWN; this.installReason = PackageManager.INSTALL_REASON_UNKNOWN; + this.mInstallScenario = PackageManager.INSTALL_SCENARIO_DEFAULT; this.forceQueryableOverride = false; this.mDataLoaderType = DataLoaderType.NONE; this.requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST; - this.mPackageLite = null; + this.mPackageLite = packageLite; } InstallParams(File stagedDir, IPackageInstallObserver2 observer, @@ -15346,6 +15364,7 @@ public class PackageManagerService extends IPackageManager.Stub move = null; installReason = fixUpInstallReason( installSource.installerPackageName, installerUid, sessionParams.installReason); + mInstallScenario = sessionParams.installScenario; this.observer = observer; installFlags = sessionParams.installFlags; this.installSource = installSource; @@ -16074,6 +16093,7 @@ public class PackageManagerService extends IPackageManager.Stub final int traceCookie; final PackageParser.SigningDetails signingDetails; final int installReason; + final int mInstallScenario; final boolean forceQueryableOverride; final int mDataLoaderType; @@ -16089,7 +16109,8 @@ public class PackageManagerService extends IPackageManager.Stub List<String> whitelistedRestrictedPermissions, int autoRevokePermissionsMode, String traceMethod, int traceCookie, SigningDetails signingDetails, - int installReason, boolean forceQueryableOverride, int dataLoaderType) { + int installReason, int installScenario, boolean forceQueryableOverride, + int dataLoaderType) { this.origin = origin; this.move = move; this.installFlags = installFlags; @@ -16106,6 +16127,7 @@ public class PackageManagerService extends IPackageManager.Stub this.traceCookie = traceCookie; this.signingDetails = signingDetails; this.installReason = installReason; + this.mInstallScenario = installScenario; this.forceQueryableOverride = forceQueryableOverride; this.mDataLoaderType = dataLoaderType; } @@ -16118,7 +16140,8 @@ public class PackageManagerService extends IPackageManager.Stub params.grantedRuntimePermissions, params.whitelistedRestrictedPermissions, params.autoRevokePermissionsMode, params.traceMethod, params.traceCookie, params.signingDetails, - params.installReason, params.forceQueryableOverride, params.mDataLoaderType); + params.installReason, params.mInstallScenario, params.forceQueryableOverride, + params.mDataLoaderType); } abstract int copyApk(); @@ -16207,8 +16230,8 @@ public class PackageManagerService extends IPackageManager.Stub super(OriginInfo.fromNothing(), null, null, 0, InstallSource.EMPTY, null, null, instructionSets, null, null, null, MODE_DEFAULT, null, 0, PackageParser.SigningDetails.UNKNOWN, - PackageManager.INSTALL_REASON_UNKNOWN, false, - DataLoaderType.NONE); + PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.INSTALL_SCENARIO_DEFAULT, + false, DataLoaderType.NONE); this.codeFile = (codePath != null) ? new File(codePath) : null; } @@ -17534,6 +17557,26 @@ public class PackageManagerService extends IPackageManager.Stub resolveUserIds(reconciledPkg.installArgs.user.getIdentifier()), /* updateReferenceProfileContent= */ true); + // Compute the compilation reason from the installation scenario. + final int compilationReason = mDexManager.getCompilationReasonForInstallScenario( + reconciledPkg.installArgs.mInstallScenario); + + // Construct the DexoptOptions early to see if we should skip running dexopt. + // + // Do not run PackageDexOptimizer through the local performDexOpt + // method because `pkg` may not be in `mPackages` yet. + // + // Also, don't fail application installs if the dexopt step fails. + final boolean isBackupOrRestore = + reconciledPkg.installArgs.installReason == INSTALL_REASON_DEVICE_RESTORE + || reconciledPkg.installArgs.installReason == INSTALL_REASON_DEVICE_SETUP; + + final int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE + | DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE + | (isBackupOrRestore ? DexoptOptions.DEXOPT_FOR_RESTORE : 0); + DexoptOptions dexoptOptions = + new DexoptOptions(packageName, compilationReason, dexoptFlags); + // Check whether we need to dexopt the app. // // NOTE: it is IMPORTANT to call dexopt: @@ -17554,11 +17597,18 @@ public class PackageManagerService extends IPackageManager.Stub // continuous progress to the useur instead of mysteriously blocking somewhere in the // middle of running an instant app. The default behaviour can be overridden // via gservices. + // + // Furthermore, dexopt may be skipped, depending on the install scenario and current + // state of the device. + // + // TODO(b/174695087): instantApp and onIncremental should be removed and their install + // path moved to SCENARIO_FAST. final boolean performDexopt = (!instantApp || Global.getInt(mContext.getContentResolver(), Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0) && !pkg.isDebuggable() - && (!onIncremental); + && (!onIncremental) + && dexoptOptions.isCompilationEnabled(); if (performDexopt) { // Compile the layout resources. @@ -17569,19 +17619,6 @@ public class PackageManagerService extends IPackageManager.Stub } Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt"); - // Do not run PackageDexOptimizer through the local performDexOpt - // method because `pkg` may not be in `mPackages` yet. - // - // Also, don't fail application installs if the dexopt step fails. - int flags = DexoptOptions.DEXOPT_BOOT_COMPLETE - | DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE; - if (reconciledPkg.installArgs.installReason == INSTALL_REASON_DEVICE_RESTORE - || reconciledPkg.installArgs.installReason == INSTALL_REASON_DEVICE_SETUP) { - flags |= DexoptOptions.DEXOPT_FOR_RESTORE; - } - DexoptOptions dexoptOptions = new DexoptOptions(packageName, - REASON_INSTALL, - flags); ScanResult result = reconciledPkg.scanResult; // This mirrors logic from commitReconciledScanResultLocked, where the library files @@ -24156,8 +24193,12 @@ public class PackageManagerService extends IPackageManager.Stub final Message msg = mHandler.obtainMessage(INIT_COPY); final OriginInfo origin = OriginInfo.fromExistingFile(codeFile); + final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing(); + final ParseResult<PackageLite> ret = ApkLiteParseUtils.parsePackageLite(input, + new File(origin.resolvedPath), /* flags */ 0); + final PackageLite lite = ret.isSuccess() ? ret.getResult() : null; final InstallParams params = new InstallParams(origin, move, installObserver, installFlags, - installSource, volumeUuid, user, packageAbiOverride); + installSource, volumeUuid, user, packageAbiOverride, lite); params.setTraceMethod("movePackage").setTraceCookie(System.identityHashCode(params)); msg.obj = params; diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java index 5fc5bac0c8c2..9cd55a6bb07e 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java @@ -18,6 +18,8 @@ package com.android.server.pm; import android.os.SystemProperties; +import com.android.server.pm.dex.DexoptOptions; + import dalvik.system.DexFile; /** @@ -26,10 +28,22 @@ import dalvik.system.DexFile; public class PackageManagerServiceCompilerMapping { // Names for compilation reasons. public static final String REASON_STRINGS[] = { - "first-boot", "boot", "install", "bg-dexopt", "ab-ota", "inactive", "shared" + "first-boot", + "boot", + "install", + "install-fast", + "install-bulk", + "install-bulk-secondary", + "install-bulk-downgraded", + "install-bulk-secondary-downgraded", + "bg-dexopt", + "ab-ota", + "inactive", + // "shared" must be the last entry + "shared" }; - static final int REASON_SHARED_INDEX = 6; + static final int REASON_SHARED_INDEX = REASON_STRINGS.length - 1; // Static block to ensure the strings array is of the right length. static { @@ -53,8 +67,9 @@ public class PackageManagerServiceCompilerMapping { // exception in case the reason or value are invalid. private static String getAndCheckValidity(int reason) { String sysPropValue = SystemProperties.get(getSystemPropertyName(reason)); - if (sysPropValue == null || sysPropValue.isEmpty() || - !DexFile.isValidCompilerFilter(sysPropValue)) { + if (sysPropValue == null || sysPropValue.isEmpty() + || !(sysPropValue.equals(DexoptOptions.COMPILER_FILTER_NOOP) + || DexFile.isValidCompilerFilter(sysPropValue))) { throw new IllegalStateException("Value \"" + sysPropValue +"\" not valid " + "(reason " + REASON_STRINGS[reason] + ")"); } else if (!isFilterAllowedForReason(reason, sysPropValue)) { diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index c77eda161c67..d3d7c6055fce 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -822,7 +822,7 @@ public class PackageManagerServiceUtils { public static PackageInfoLite getMinimalPackageInfo(Context context, PackageParser.PackageLite pkg, String packagePath, int flags, String abiOverride) { final PackageInfoLite ret = new PackageInfoLite(); - if (packagePath == null) { + if (packagePath == null || pkg == null) { Slog.i(TAG, "Invalid package file " + packagePath); ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK; return ret; diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 318b2293a13a..2f6756dc01ee 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -27,7 +27,6 @@ import android.accounts.IAccountManager; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManagerInternal; -import android.app.role.IRoleManager; import android.app.role.RoleManager; import android.content.ComponentName; import android.content.Context; @@ -80,7 +79,6 @@ import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor.AutoCloseInputStream; import android.os.PersistableBundle; import android.os.Process; -import android.os.RemoteCallback; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceSpecificException; @@ -106,6 +104,7 @@ import com.android.internal.content.PackageHelper; import com.android.internal.util.ArrayUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; +import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.SystemConfig; import com.android.server.pm.PackageManagerShellCommandDataLoader.Metadata; @@ -2971,12 +2970,10 @@ class PackageManagerShellCommand extends ShellCommand { final int translatedUserId = translateUserId(userId, UserHandle.USER_NULL, "runSetHomeActivity"); final CompletableFuture<Boolean> future = new CompletableFuture<>(); - final RemoteCallback callback = new RemoteCallback(res -> future.complete(res != null)); try { - IRoleManager roleManager = android.app.role.IRoleManager.Stub.asInterface( - ServiceManager.getServiceOrThrow(Context.ROLE_SERVICE)); - roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, pkgName, - 0, translatedUserId, callback); + RoleManager roleManager = mContext.getSystemService(RoleManager.class); + roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, pkgName, 0, + UserHandle.of(translatedUserId), FgThread.getExecutor(), future::complete); boolean success = future.get(); if (success) { pw.println("Success"); diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java index 47d0a3d561b1..c182d685c247 100644 --- a/services/core/java/com/android/server/pm/UserManagerInternal.java +++ b/services/core/java/com/android/server/pm/UserManagerInternal.java @@ -57,6 +57,20 @@ public abstract class UserManagerInternal { } /** + * Listener for user lifecycle events. + * + * <p><b>NOTE: </b>implementations MUST not block the current thread. + */ + public interface UserLifecycleListener { + + /** Called when a new user is created. */ + default void onUserCreated(UserInfo user) {} + + /** Called when an existing user is removed. */ + default void onUserRemoved(UserInfo user) {} + } + + /** * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to set * restrictions enforced by the user. * @@ -97,6 +111,12 @@ public abstract class UserManagerInternal { /** Remove a {@link UserRestrictionsListener}. */ public abstract void removeUserRestrictionsListener(UserRestrictionsListener listener); + /** Adds a {@link UserLifecycleListener}. */ + public abstract void addUserLifecycleListener(UserLifecycleListener listener); + + /** Removes a {@link UserLifecycleListener}. */ + public abstract void removeUserLifecycleListener(UserLifecycleListener listener); + /** * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to update * whether the device is managed by device owner. diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 62ac57062ac6..ccbf73ca9ab0 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -110,6 +110,7 @@ import com.android.server.LocalServices; import com.android.server.LockGuard; import com.android.server.SystemService; import com.android.server.am.UserState; +import com.android.server.pm.UserManagerInternal.UserLifecycleListener; import com.android.server.pm.UserManagerInternal.UserRestrictionsListener; import com.android.server.storage.DeviceStorageMonitorInternal; import com.android.server.utils.TimingsTraceAndSlog; @@ -438,6 +439,9 @@ public class UserManagerService extends IUserManager.Stub { private final ArrayList<UserRestrictionsListener> mUserRestrictionsListeners = new ArrayList<>(); + @GuardedBy("mUserRemovedListeners") + private final ArrayList<UserLifecycleListener> mUserLifecycleListeners = new ArrayList<>(); + private final LockPatternUtils mLockPatternUtils; private final String ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK = @@ -3633,6 +3637,14 @@ public class UserManagerService extends IUserManager.Stub { } private void dispatchUserAdded(@NonNull UserInfo userInfo) { + // Notify internal listeners first... + synchronized (mUserLifecycleListeners) { + for (int i = 0; i < mUserLifecycleListeners.size(); i++) { + mUserLifecycleListeners.get(i).onUserCreated(userInfo); + } + } + + //...then external ones Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED); addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userInfo.id); // Also, add the UserHandle for mainline modules which can't use the @hide @@ -4018,13 +4030,19 @@ public class UserManagerService extends IUserManager.Stub { user = getUserInfoLU(userId); } if (user != null && user.preCreated) { - Slog.i(LOG_TAG, "Removing a precreated user with user id: " + userId); + Slog.i(LOG_TAG, "Removing a pre-created user with user id: " + userId); // Don't want to fire ACTION_USER_REMOVED, so cleanup the state and exit early. LocalServices.getService(ActivityTaskManagerInternal.class).onUserStopped(userId); removeUserState(userId); return; } + synchronized (mUserLifecycleListeners) { + for (int i = 0; i < mUserLifecycleListeners.size(); i++) { + mUserLifecycleListeners.get(i).onUserRemoved(user); + } + } + // Let other services shutdown any activity and clean up their state before completely // wiping the user's system directory and removing from the user list final long ident = Binder.clearCallingIdentity(); @@ -4960,6 +4978,15 @@ public class UserManagerService extends IUserManager.Stub { pw.println(" System user allocations: " + mUser0Allocations.get()); } + pw.println(); + pw.println("Number of listeners for"); + synchronized (mUserRestrictionsListeners) { + pw.println(" restrictions: " + mUserRestrictionsListeners.size()); + } + synchronized (mUserLifecycleListeners) { + pw.println(" user lifecycle events: " + mUserLifecycleListeners.size()); + } + // Dump UserTypes pw.println(); pw.println("User types version: " + mUserTypeVersion); @@ -5078,6 +5105,20 @@ public class UserManagerService extends IUserManager.Stub { } @Override + public void addUserLifecycleListener(UserLifecycleListener listener) { + synchronized (mUserLifecycleListeners) { + mUserLifecycleListeners.add(listener); + } + } + + @Override + public void removeUserLifecycleListener(UserLifecycleListener listener) { + synchronized (mUserLifecycleListeners) { + mUserLifecycleListeners.remove(listener); + } + } + + @Override public void setDeviceManaged(boolean isManaged) { synchronized (mUsersLock) { mIsDeviceManaged = isManaged; diff --git a/services/core/java/com/android/server/pm/UserTypeFactory.java b/services/core/java/com/android/server/pm/UserTypeFactory.java index 1d3aecdca8dd..1ffbf608c6d7 100644 --- a/services/core/java/com/android/server/pm/UserTypeFactory.java +++ b/services/core/java/com/android/server/pm/UserTypeFactory.java @@ -30,6 +30,7 @@ import static android.os.UserManager.USER_TYPE_FULL_RESTRICTED; import static android.os.UserManager.USER_TYPE_FULL_SECONDARY; import static android.os.UserManager.USER_TYPE_FULL_SYSTEM; import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED; +import static android.os.UserManager.USER_TYPE_PROFILE_TEST; import static android.os.UserManager.USER_TYPE_SYSTEM_HEADLESS; import static com.android.server.pm.UserTypeDetails.UNLIMITED_NUMBER_OF_USERS; @@ -37,6 +38,7 @@ import static com.android.server.pm.UserTypeDetails.UNLIMITED_NUMBER_OF_USERS; import android.content.pm.UserInfo; import android.content.res.Resources; import android.content.res.XmlResourceParser; +import android.os.Build; import android.os.Bundle; import android.os.UserManager; import android.util.ArrayMap; @@ -98,6 +100,9 @@ public final class UserTypeFactory { builders.put(USER_TYPE_FULL_DEMO, getDefaultTypeFullDemo()); builders.put(USER_TYPE_FULL_RESTRICTED, getDefaultTypeFullRestricted()); builders.put(USER_TYPE_SYSTEM_HEADLESS, getDefaultTypeSystemHeadless()); + if (Build.IS_DEBUGGABLE) { + builders.put(USER_TYPE_PROFILE_TEST, getDefaultTypeProfileTest()); + } return builders; } @@ -132,6 +137,37 @@ public final class UserTypeFactory { } /** + * Returns the Builder for the default {@link UserManager#USER_TYPE_PROFILE_TEST} + * configuration (for userdebug builds). For now it just uses managed profile badges. + */ + private static UserTypeDetails.Builder getDefaultTypeProfileTest() { + final Bundle restrictions = new Bundle(); + restrictions.putBoolean(UserManager.DISALLOW_FUN, true); + + return new UserTypeDetails.Builder() + .setName(USER_TYPE_PROFILE_TEST) + .setBaseType(FLAG_PROFILE) + .setMaxAllowedPerParent(2) + .setLabel(0) + .setIconBadge(com.android.internal.R.drawable.ic_corp_icon_badge_case) + .setBadgePlain(com.android.internal.R.drawable.ic_corp_badge_case) + .setBadgeNoBackground(com.android.internal.R.drawable.ic_corp_badge_no_background) + .setBadgeLabels( + com.android.internal.R.string.managed_profile_label_badge, + com.android.internal.R.string.managed_profile_label_badge_2, + com.android.internal.R.string.managed_profile_label_badge_3) + .setBadgeColors( + com.android.internal.R.color.profile_badge_1, + com.android.internal.R.color.profile_badge_2, + com.android.internal.R.color.profile_badge_3) + .setDarkThemeBadgeColors( + com.android.internal.R.color.profile_badge_1_dark, + com.android.internal.R.color.profile_badge_2_dark, + com.android.internal.R.color.profile_badge_3_dark) + .setDefaultRestrictions(restrictions); + } + + /** * Returns the Builder for the default {@link UserManager#USER_TYPE_FULL_SECONDARY} * configuration. */ diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java index fadd0c850f18..139654ef4561 100644 --- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java +++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java @@ -579,6 +579,8 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { // Constants used for logging compilation reason to TRON. // DO NOT CHANGE existing values. // + // In the below constants, the abbreviation DM stands for "DEX metadata". + // // NOTE: '-1' value is reserved for the case where we cannot produce a valid // PackageOptimizationInfo because the ArtManagerInternal is not ready to be used by the // ActivityMetricsLoggers. @@ -591,7 +593,18 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { private static final int TRON_COMPILATION_REASON_AB_OTA = 6; private static final int TRON_COMPILATION_REASON_INACTIVE = 7; private static final int TRON_COMPILATION_REASON_SHARED = 8; - private static final int TRON_COMPILATION_REASON_INSTALL_WITH_DEX_METADATA = 9; + private static final int TRON_COMPILATION_REASON_INSTALL_WITH_DM = 9; + private static final int TRON_COMPILATION_REASON_INSTALL_FAST = 10; + private static final int TRON_COMPILATION_REASON_INSTALL_BULK = 11; + private static final int TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY = 12; + private static final int TRON_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED = 13; + private static final int TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED = 14; + private static final int TRON_COMPILATION_REASON_INSTALL_FAST_WITH_DM = 15; + private static final int TRON_COMPILATION_REASON_INSTALL_BULK_WITH_DM = 16; + private static final int TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_WITH_DM = 17; + private static final int TRON_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED_WITH_DM = 18; + private static final int + TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED_WITH_DM = 19; // The annotation to add as a suffix to the compilation reason when dexopt was // performed with dex metadata. @@ -611,10 +624,30 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { case "ab-ota" : return TRON_COMPILATION_REASON_AB_OTA; case "inactive" : return TRON_COMPILATION_REASON_INACTIVE; case "shared" : return TRON_COMPILATION_REASON_SHARED; - // This is a special marker for dex metadata installation that does not + case "install-fast" : + return TRON_COMPILATION_REASON_INSTALL_FAST; + case "install-bulk" : + return TRON_COMPILATION_REASON_INSTALL_BULK; + case "install-bulk-secondary" : + return TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY; + case "install-bulk-downgraded" : + return TRON_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED; + case "install-bulk-secondary-downgraded" : + return TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED; + // These are special markers for dex metadata installation that do not // have an equivalent as a system property. case "install" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : - return TRON_COMPILATION_REASON_INSTALL_WITH_DEX_METADATA; + return TRON_COMPILATION_REASON_INSTALL_WITH_DM; + case "install-fast" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : + return TRON_COMPILATION_REASON_INSTALL_FAST_WITH_DM; + case "install-bulk" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : + return TRON_COMPILATION_REASON_INSTALL_BULK_WITH_DM; + case "install-bulk-secondary" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : + return TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_WITH_DM; + case "install-bulk-downgraded" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : + return TRON_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED_WITH_DM; + case "install-bulk-secondary-downgraded" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : + return TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED_WITH_DM; default: return TRON_COMPILATION_REASON_UNKNOWN; } } diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java index 3074250950f7..cc6d80a2aeec 100644 --- a/services/core/java/com/android/server/pm/dex/DexManager.java +++ b/services/core/java/com/android/server/pm/dex/DexManager.java @@ -27,8 +27,11 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.content.pm.PackagePartitions; +import android.os.BatteryManager; import android.os.FileUtils; +import android.os.PowerManager; import android.os.RemoteException; import android.os.SystemProperties; import android.os.UserHandle; @@ -107,6 +110,13 @@ public class DexManager { @GuardedBy("mInstallLock") private final Installer mInstaller; + private BatteryManager mBatteryManager = null; + private PowerManager mPowerManager = null; + + // An integer percentage value used to determine when the device is considered to be on low + // power for compilation purposes. + private final int mCriticalBatteryLevel; + // Possible outcomes of a dex search. private static int DEX_SEARCH_NOT_FOUND = 0; // dex file not found private static int DEX_SEARCH_FOUND_PRIMARY = 1; // dex file is the primary/base apk @@ -123,6 +133,23 @@ public class DexManager { mInstaller = installer; mInstallLock = installLock; mDynamicCodeLogger = new DynamicCodeLogger(pms, installer); + + // This is currently checked to handle tests that pass in a null context. + // TODO(b/174783329): Modify the tests to pass in a mocked Context, PowerManager, + // and BatteryManager. + if (mContext != null) { + mPowerManager = mContext.getSystemService(PowerManager.class); + + if (mPowerManager == null) { + Slog.wtf(TAG, "Power Manager is unavailable at time of Dex Manager start"); + } + + mCriticalBatteryLevel = mContext.getResources().getInteger( + com.android.internal.R.integer.config_criticalBatteryWarningLevel); + } else { + // This value will never be used as the Battery Manager null check will fail first. + mCriticalBatteryLevel = 0; + } } public DynamicCodeLogger getDynamicCodeLogger() { @@ -905,6 +932,74 @@ public class DexManager { } } + /** + * Translates install scenarios into compilation reasons. This process can be influenced + * by the state of the device. + */ + public int getCompilationReasonForInstallScenario(int installScenario) { + // Compute the compilation reason from the installation scenario. + + boolean resourcesAreCritical = areBatteryThermalOrMemoryCritical(); + switch (installScenario) { + case PackageManager.INSTALL_SCENARIO_DEFAULT: { + return PackageManagerService.REASON_INSTALL; + } + case PackageManager.INSTALL_SCENARIO_FAST: { + return PackageManagerService.REASON_INSTALL_FAST; + } + case PackageManager.INSTALL_SCENARIO_BULK: { + if (resourcesAreCritical) { + return PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED; + } else { + return PackageManagerService.REASON_INSTALL_BULK; + } + } + case PackageManager.INSTALL_SCENARIO_BULK_SECONDARY: { + if (resourcesAreCritical) { + return PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED; + } else { + return PackageManagerService.REASON_INSTALL_BULK_SECONDARY; + } + } + default: { + throw new IllegalArgumentException("Invalid installation scenario"); + } + } + } + + /** + * Fetches the battery manager object and caches it if it hasn't been fetched already. + */ + private BatteryManager getBatteryManager() { + if (mBatteryManager == null) { + mBatteryManager = mContext.getSystemService(BatteryManager.class); + } + + return mBatteryManager; + } + + /** + * Returns true if the battery level, device temperature, or memory usage are considered to be + * in a critical state. + */ + private boolean areBatteryThermalOrMemoryCritical() { + BatteryManager batteryManager = getBatteryManager(); + boolean isBtmCritical = (batteryManager != null + && batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_STATUS) + == BatteryManager.BATTERY_STATUS_DISCHARGING + && batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) + <= mCriticalBatteryLevel) + || (mPowerManager != null + && mPowerManager.getCurrentThermalStatus() + >= PowerManager.THERMAL_STATUS_SEVERE); + + if (DEBUG) { + Log.d(TAG, "Battery, thermal, or memory are critical: " + isBtmCritical); + } + + return isBtmCritical; + } + public static class RegisterDexModuleResult { public RegisterDexModuleResult() { this(false, null); diff --git a/services/core/java/com/android/server/pm/dex/DexoptOptions.java b/services/core/java/com/android/server/pm/dex/DexoptOptions.java index 68f38861d7e4..ea233161b4af 100644 --- a/services/core/java/com/android/server/pm/dex/DexoptOptions.java +++ b/services/core/java/com/android/server/pm/dex/DexoptOptions.java @@ -65,6 +65,12 @@ public final class DexoptOptions { // or device setup and should be scheduled appropriately. public static final int DEXOPT_FOR_RESTORE = 1 << 11; // TODO(b/135202722): remove + /** + * A value indicating that dexopt shouldn't be run. This string is only used when loading + * filters from the `pm.dexopt.install*` properties and is not propagated to dex2oat. + */ + public static final String COMPILER_FILTER_NOOP = "skip"; + // The name of package to optimize. private final String mPackageName; @@ -176,6 +182,10 @@ public final class DexoptOptions { return mCompilationReason; } + public boolean isCompilationEnabled() { + return !mCompilerFilter.equals(COMPILER_FILTER_NOOP); + } + /** * Creates a new set of DexoptOptions which are the same with the exception of the compiler * filter (set to the given value). diff --git a/services/core/java/com/android/server/pm/permission/OWNERS b/services/core/java/com/android/server/pm/permission/OWNERS index 0e88862e01b1..6e678305b860 100644 --- a/services/core/java/com/android/server/pm/permission/OWNERS +++ b/services/core/java/com/android/server/pm/permission/OWNERS @@ -1,7 +1,7 @@ moltmann@google.com zhanghai@google.com -per-file DefaultPermissionGrantPolicy.java = hackbod@android.com -per-file DefaultPermissionGrantPolicy.java = jsharkey@android.com +per-file DefaultPermissionGrantPolicy.java = hackbod@google.com +per-file DefaultPermissionGrantPolicy.java = jsharkey@google.com per-file DefaultPermissionGrantPolicy.java = svetoslavganov@google.com per-file DefaultPermissionGrantPolicy.java = toddke@google.com per-file DefaultPermissionGrantPolicy.java = yamasani@google.com diff --git a/services/core/java/com/android/server/pm/permission/Permission.java b/services/core/java/com/android/server/pm/permission/Permission.java index 995b59e97e91..30c334d22b6a 100644 --- a/services/core/java/com/android/server/pm/permission/Permission.java +++ b/services/core/java/com/android/server/pm/permission/Permission.java @@ -61,6 +61,7 @@ public final class Permission { PermissionInfo.PROTECTION_NORMAL, PermissionInfo.PROTECTION_SIGNATURE, PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM, + PermissionInfo.PROTECTION_INTERNAL, }) @Retention(RetentionPolicy.SOURCE) public @interface ProtectionLevel {} @@ -246,6 +247,11 @@ public final class Permission { == PermissionInfo.PROTECTION_SIGNATURE; } + public boolean isInternal() { + return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) + == PermissionInfo.PROTECTION_INTERNAL; + } + public boolean isAppOp() { return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0; } @@ -335,6 +341,10 @@ public final class Permission { return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_RECENTS) != 0; } + public boolean isRole() { + return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_ROLE) != 0; + } + public void transfer(@NonNull String oldPackageName, @NonNull String newPackageName) { if (!oldPackageName.equals(mPermissionInfo.packageName)) { return; diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 791efd022fe9..1df51772f823 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -160,6 +160,7 @@ import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -1550,18 +1551,24 @@ public class PermissionManagerService extends IPermissionManager.Stub { throw new IllegalArgumentException("Unknown package: " + packageName); } + final boolean isRolePermission; final boolean isSoftRestrictedPermission; synchronized (mLock) { final Permission permission = mRegistry.getPermission(permName); - isSoftRestrictedPermission = permission != null && permission.isSoftRestricted(); + if (permission == null) { + throw new IllegalArgumentException("Unknown permission: " + permName); + } + isRolePermission = permission.isRole(); + isSoftRestrictedPermission = permission.isSoftRestricted(); } + final boolean mayGrantRolePermission = isRolePermission + && mayManageRolePermission(callingUid); final boolean mayGrantSoftRestrictedPermission = isSoftRestrictedPermission && SoftRestrictedPermissionPolicy.forPermission(mContext, pkg.toAppInfoWithoutState(), pkg, UserHandle.of(userId), permName) .mayGrantPermission(); final boolean isRuntimePermission; - final boolean isDevelopmentPermission; final boolean permissionHasGids; synchronized (mLock) { final Permission bp = mRegistry.getPermission(permName); @@ -1570,9 +1577,14 @@ public class PermissionManagerService extends IPermissionManager.Stub { } isRuntimePermission = bp.isRuntime(); - isDevelopmentPermission = bp.isDevelopment(); permissionHasGids = bp.hasGids(); - if (!(isRuntimePermission || isDevelopmentPermission)) { + if (isRuntimePermission || bp.isDevelopment()) { + // Good. + } else if (bp.isRole()) { + if (!mayGrantRolePermission) { + throw new SecurityException("Permission " + permName + " is managed by role"); + } + } else { throw new SecurityException("Permission " + permName + " requested by " + pkg.getPackageName() + " is not a changeable permission type"); } @@ -1623,7 +1635,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { return; } - if (bp.isDevelopment()) { + if (bp.isDevelopment() || bp.isRole()) { // Development permissions must be handled specially, since they are not // normal runtime permissions. For now they apply to all users. // TODO(zhanghai): We are breaking the behavior above by making all permission state @@ -1654,10 +1666,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { final int uid = UserHandle.getUid(userId, pkg.getUid()); if (callback != null) { - if (isDevelopmentPermission) { - callback.onInstallPermissionGranted(); - } else { + if (isRuntimePermission) { callback.onPermissionGranted(uid, userId); + } else { + callback.onInstallPermissionGranted(); } if (permissionHasGids) { callback.onGidsChanged(UserHandle.getAppId(pkg.getUid()), userId); @@ -1715,8 +1727,18 @@ public class PermissionManagerService extends IPermissionManager.Stub { throw new IllegalArgumentException("Unknown package: " + packageName); } + final boolean isRolePermission; + synchronized (mLock) { + final Permission permission = mRegistry.getPermission(permName); + if (permission == null) { + throw new IllegalArgumentException("Unknown permission: " + permName); + } + isRolePermission = permission.isRole(); + } + final boolean mayRevokeRolePermission = isRolePermission + && mayManageRolePermission(callingUid); + final boolean isRuntimePermission; - final boolean isDevelopmentPermission; synchronized (mLock) { final Permission bp = mRegistry.getPermission(permName); if (bp == null) { @@ -1724,8 +1746,13 @@ public class PermissionManagerService extends IPermissionManager.Stub { } isRuntimePermission = bp.isRuntime(); - isDevelopmentPermission = bp.isDevelopment(); - if (!(isRuntimePermission || isDevelopmentPermission)) { + if (isRuntimePermission || bp.isDevelopment()) { + // Good. + } else if (bp.isRole()) { + if (!mayRevokeRolePermission) { + throw new SecurityException("Permission " + permName + " is managed by role"); + } + } else { throw new SecurityException("Permission " + permName + " requested by " + pkg.getPackageName() + " is not a changeable permission type"); } @@ -1777,11 +1804,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { } if (callback != null) { - if (isDevelopmentPermission) { - mDefaultPermissionCallback.onInstallPermissionRevoked(); - } else { + if (isRuntimePermission) { callback.onPermissionRevoked(UserHandle.getUid(userId, pkg.getUid()), userId, reason); + } else { + mDefaultPermissionCallback.onInstallPermissionRevoked(); } } @@ -1790,6 +1817,17 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } + private boolean mayManageRolePermission(int uid) { + final PackageManager packageManager = mContext.getPackageManager(); + final String[] packageNames = packageManager.getPackagesForUid(uid); + if (packageNames == null) { + return false; + } + final String permissionControllerPackageName = + packageManager.getPermissionControllerPackageName(); + return Arrays.asList(packageNames).contains(permissionControllerPackageName); + } + @Override public void resetRuntimePermissions() { mContext.enforceCallingOrSelfPermission( @@ -2679,7 +2717,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { boolean runtimePermissionsRevoked = false; int[] updatedUserIds = EMPTY_INT_ARRAY; - final ArraySet<String> shouldGrantSignaturePermission = new ArraySet<>(); + ArraySet<String> shouldGrantSignaturePermission = null; + ArraySet<String> shouldGrantInternalPermission = null; final List<String> requestedPermissions = pkg.getRequestedPermissions(); final int requestedPermissionsSize = requestedPermissions.size(); for (int i = 0; i < requestedPermissionsSize; i++) { @@ -2692,9 +2731,20 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (permission == null) { continue; } - if (permission.isSignature() && shouldGrantSignaturePermission(pkg, ps, permission)) { + if (permission.isSignature() && (shouldGrantSignaturePermission(pkg, permission) + || shouldGrantPermissionByProtectionFlags(pkg, ps, permission))) { + if (shouldGrantSignaturePermission == null) { + shouldGrantSignaturePermission = new ArraySet<>(); + } shouldGrantSignaturePermission.add(permissionName); } + if (permission.isInternal() + && shouldGrantPermissionByProtectionFlags(pkg, ps, permission)) { + if (shouldGrantInternalPermission == null) { + shouldGrantInternalPermission = new ArraySet<>(); + } + shouldGrantInternalPermission.add(permissionName); + } } final SparseBooleanArray isPermissionPolicyInitialized = new SparseBooleanArray(); @@ -2904,9 +2954,17 @@ public class PermissionManagerService extends IPermissionManager.Stub { + pkg.getPackageName()); } - if ((bp.isNormal() && shouldGrantNormalPermission) || (bp.isSignature() - && (shouldGrantSignaturePermission.contains(permName) - || (bp.isDevelopment() && origState.isPermissionGranted(permName))))) { + if ((bp.isNormal() && shouldGrantNormalPermission) + || (bp.isSignature() + && ((shouldGrantSignaturePermission != null + && shouldGrantSignaturePermission.contains(permName)) + || ((bp.isDevelopment() || bp.isRole()) + && origState.isPermissionGranted(permName)))) + || (bp.isInternal() + && ((shouldGrantInternalPermission != null + && shouldGrantInternalPermission.contains(permName)) + || ((bp.isDevelopment() || bp.isRole()) + && origState.isPermissionGranted(permName))))) { // Grant an install permission. if (uidState.grantPermission(bp)) { changedInstallPermission = true; @@ -3406,7 +3464,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { } private boolean shouldGrantSignaturePermission(@NonNull AndroidPackage pkg, - @NonNull PackageSetting pkgSetting, @NonNull Permission bp) { + @NonNull Permission bp) { // expect single system package String systemPackageName = ArrayUtils.firstOrNull(mPackageManagerInt.getKnownPackageNames( PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM)); @@ -3421,8 +3479,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { // - or it shares the above relationships with the system package final PackageParser.SigningDetails sourceSigningDetails = getSourcePackageSigningDetails(bp); - boolean allowed = - pkg.getSigningDetails().hasAncestorOrSelf(sourceSigningDetails) + return pkg.getSigningDetails().hasAncestorOrSelf(sourceSigningDetails) || sourceSigningDetails.checkCapability( pkg.getSigningDetails(), PackageParser.SigningDetails.CertCapabilities.PERMISSION) @@ -3430,6 +3487,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { || systemPackage.getSigningDetails().checkCapability( pkg.getSigningDetails(), PackageParser.SigningDetails.CertCapabilities.PERMISSION); + } + + private boolean shouldGrantPermissionByProtectionFlags(@NonNull AndroidPackage pkg, + @NonNull PackageSetting pkgSetting, @NonNull Permission bp) { + boolean allowed = false; final boolean isVendorPrivilegedPermission = bp.isVendorPrivileged(); final boolean isPrivilegedPermission = bp.isPrivileged() || isVendorPrivilegedPermission; final boolean isOemPermission = bp.isOem(); @@ -3472,12 +3534,12 @@ public class PermissionManagerService extends IPermissionManager.Stub { // need a separate flag anymore. Hence we need to check which // permissions are needed by the permission controller if (!allowed && bp.isInstaller() - && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( + && (ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM), pkg.getPackageName()) || ArrayUtils.contains( mPackageManagerInt.getKnownPackageNames( PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER, - UserHandle.USER_SYSTEM), pkg.getPackageName())) { + UserHandle.USER_SYSTEM), pkg.getPackageName()))) { // If this permission is to be granted to the system installer and // this app is an installer, then it gets the permission. allowed = true; @@ -5148,20 +5210,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { } @Override - public void retainHardAndSoftRestrictedPermissions(@NonNull List<String> permissionNames) { - synchronized (mLock) { - Iterator<String> iterator = permissionNames.iterator(); - while (iterator.hasNext()) { - final String permissionName = iterator.next(); - final Permission permission = mRegistry.getPermission(permissionName); - if (permission == null || !permission.isHardOrSoftRestricted()) { - iterator.remove(); - } - } - } - } - - @Override public void readLegacyPermissionsTEMP( @NonNull LegacyPermissionSettings legacyPermissionSettings) { PermissionManagerService.this.readLegacyPermissions(legacyPermissionSettings); diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java index 66e692db2154..0817d4fc895e 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java @@ -184,12 +184,6 @@ public interface PermissionManagerServiceInternal extends PermissionManagerInter void stopShellPermissionIdentityDelegation(); /** - * Removes invalid permissions which are not {@link PermissionInfo#FLAG_HARD_RESTRICTED} or - * {@link PermissionInfo#FLAG_SOFT_RESTRICTED} from the input. - */ - void retainHardAndSoftRestrictedPermissions(@NonNull List<String> permissionNames); - - /** * Read legacy permissions from legacy permission settings. * * TODO(zhanghai): This is a temporary method because we should not expose diff --git a/services/core/java/com/android/server/policy/OWNERS b/services/core/java/com/android/server/policy/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/services/core/java/com/android/server/policy/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 75868e3216cc..ea985df1c6b8 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -2413,15 +2413,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { wm = (WindowManager) context.getSystemService(WINDOW_SERVICE); view = win.getDecorView(); - // Ignore to show splash screen if the decorView is not opaque. - if (!view.isOpaque()) { - if (DEBUG_SPLASH_SCREEN) { - Slog.d(TAG, "addSplashScreen: the view of " + packageName - + " is not opaque, cancel it"); - } - return null; - } - if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "Adding splash screen window for " + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null)); diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java index 68d038bb5cf6..16f50694ebb9 100644 --- a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java +++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java @@ -113,11 +113,6 @@ public class BatterySaverController implements BatterySaverPolicyListener { private boolean mIsInteractive; /** - * Read-only list of plugins. No need for synchronization. - */ - private final Plugin[] mPlugins; - - /** * Package name that will receive an explicit manifest broadcast for * {@link PowerManager#ACTION_POWER_SAVE_MODE_CHANGED}. It's {@code null} if it hasn't been * retrieved yet. @@ -172,15 +167,6 @@ public class BatterySaverController implements BatterySaverPolicyListener { } } - /** - * Plugin interface. All methods are guaranteed to be called on the same (handler) thread. - */ - public interface Plugin { - void onSystemReady(BatterySaverController caller); - - void onBatterySaverChanged(BatterySaverController caller); - } - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -194,6 +180,7 @@ public class BatterySaverController implements BatterySaverPolicyListener { updateBatterySavingStats(); return; // No need to send it if not enabled. } + // We currently evaluate state only for CPU frequency changes. // Don't send the broadcast, because we never did so in this case. mHandler.postStateChanged(/*sendBroadcast=*/ false, REASON_INTERACTIVE_CHANGED); @@ -224,9 +211,6 @@ public class BatterySaverController implements BatterySaverPolicyListener { mFileUpdater = new FileUpdater(context); mBatterySavingStats = batterySavingStats; - // TODO(79580230): remove plugin code and maybe screen on/off listeners? - // Initialize plugins. - mPlugins = new Plugin[0]; PowerManager.invalidatePowerSaveModeCaches(); } @@ -300,12 +284,6 @@ public class BatterySaverController implements BatterySaverPolicyListener { msg.arg1 == ARG_SEND_BROADCAST, msg.arg2); break; - - case MSG_SYSTEM_READY: - for (Plugin p : mPlugins) { - p.onSystemReady(BatterySaverController.this); - } - break; } } } @@ -479,10 +457,6 @@ public class BatterySaverController implements BatterySaverPolicyListener { mFileUpdater.writeFiles(fileValues); } - for (Plugin p : mPlugins) { - p.onBatterySaverChanged(this); - } - if (sendBroadcast) { if (DEBUG) { diff --git a/services/core/java/com/android/server/powerstats/OWNERS b/services/core/java/com/android/server/powerstats/OWNERS new file mode 100644 index 000000000000..d68066bb8c40 --- /dev/null +++ b/services/core/java/com/android/server/powerstats/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/power/OWNERS diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java index eb15c808f512..caa275d266e9 100644 --- a/services/core/java/com/android/server/role/RoleManagerService.java +++ b/services/core/java/com/android/server/role/RoleManagerService.java @@ -34,7 +34,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; import android.content.pm.Signature; @@ -754,18 +753,6 @@ public class RoleManagerService extends SystemService implements RoleUserState.C dumpOutputStream.flush(); } - - private int getUidForPackage(String packageName) { - final long ident = Binder.clearCallingIdentity(); - try { - return getContext().getPackageManager().getApplicationInfo(packageName, - PackageManager.MATCH_ANY_USER).uid; - } catch (NameNotFoundException nnfe) { - return -1; - } finally { - Binder.restoreCallingIdentity(ident); - } - } } private class Internal extends RoleManagerInternal { diff --git a/services/core/java/com/android/server/rollback/OWNERS b/services/core/java/com/android/server/rollback/OWNERS new file mode 100644 index 000000000000..7feb85f929cd --- /dev/null +++ b/services/core/java/com/android/server/rollback/OWNERS @@ -0,0 +1 @@ +olilan@google.com diff --git a/services/core/java/com/android/server/slice/OWNERS b/services/core/java/com/android/server/slice/OWNERS new file mode 100644 index 000000000000..3d0859f6f701 --- /dev/null +++ b/services/core/java/com/android/server/slice/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/slice/OWNERS diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index cf20cf4c0c9f..49f9b311d95c 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -31,6 +31,7 @@ import static android.net.NetworkTemplate.buildTemplateMobileWithRatType; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; import static android.net.NetworkTemplate.getAllCollapsedRatTypes; import static android.os.Debug.getIonHeapsSizeKb; +import static android.os.Process.LAST_SHARED_APPLICATION_GID; import static android.os.Process.getUidForPid; import static android.os.storage.VolumeInfo.TYPE_PRIVATE; import static android.os.storage.VolumeInfo.TYPE_PUBLIC; @@ -1517,14 +1518,53 @@ public class StatsPullAtomService extends SystemService { } int pullCpuTimePerUidFreqLocked(int atomTag, List<StatsEvent> pulledData) { + // Aggregate times for the same uids. + SparseArray<long[]> aggregated = new SparseArray<>(); mCpuUidFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> { - for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) { - if (cpuFreqTimeMs[freqIndex] >= MIN_CPU_TIME_PER_UID_FREQ) { - pulledData.add(FrameworkStatsLog.buildStatsEvent( - atomTag, uid, freqIndex, cpuFreqTimeMs[freqIndex])); + // For uids known to be aggregated from many entries allow mutating in place to avoid + // many copies. Otherwise, copy before aggregating. + boolean mutateInPlace = false; + if (UserHandle.isIsolated(uid)) { + // Skip individual isolated uids because they are recycled and quickly removed from + // the underlying data source. + return; + } else if (UserHandle.isSharedAppGid(uid)) { + // All shared app gids are accounted together. + uid = LAST_SHARED_APPLICATION_GID; + mutateInPlace = true; + } else if (UserHandle.isApp(uid)) { + // Apps are accounted under their app id. + uid = UserHandle.getAppId(uid); + } + + long[] aggCpuFreqTimeMs = aggregated.get(uid); + if (aggCpuFreqTimeMs != null) { + if (!mutateInPlace) { + aggCpuFreqTimeMs = Arrays.copyOf(aggCpuFreqTimeMs, cpuFreqTimeMs.length); + aggregated.put(uid, aggCpuFreqTimeMs); + } + for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) { + aggCpuFreqTimeMs[freqIndex] += cpuFreqTimeMs[freqIndex]; } + } else { + if (mutateInPlace) { + cpuFreqTimeMs = Arrays.copyOf(cpuFreqTimeMs, cpuFreqTimeMs.length); + } + aggregated.put(uid, cpuFreqTimeMs); } }); + + int size = aggregated.size(); + for (int i = 0; i < size; ++i) { + int uid = aggregated.keyAt(i); + long[] aggCpuFreqTimeMs = aggregated.valueAt(i); + for (int freqIndex = 0; freqIndex < aggCpuFreqTimeMs.length; ++freqIndex) { + if (aggCpuFreqTimeMs[freqIndex] >= MIN_CPU_TIME_PER_UID_FREQ) { + pulledData.add(FrameworkStatsLog.buildStatsEvent( + atomTag, uid, freqIndex, aggCpuFreqTimeMs[freqIndex])); + } + } + } return StatsManager.PULL_SUCCESS; } diff --git a/services/core/java/com/android/server/statusbar/OWNERS b/services/core/java/com/android/server/statusbar/OWNERS new file mode 100644 index 000000000000..2e96c97c8bb3 --- /dev/null +++ b/services/core/java/com/android/server/statusbar/OWNERS @@ -0,0 +1 @@ +include /packages/SystemUI/OWNERS diff --git a/services/core/java/com/android/server/storage/OWNERS b/services/core/java/com/android/server/storage/OWNERS new file mode 100644 index 000000000000..6f9dbea36b06 --- /dev/null +++ b/services/core/java/com/android/server/storage/OWNERS @@ -0,0 +1 @@ +include /core/java/android/os/storage/OWNERS diff --git a/services/core/java/com/android/server/textclassifier/OWNERS b/services/core/java/com/android/server/textclassifier/OWNERS new file mode 100644 index 000000000000..46b3cb8824a0 --- /dev/null +++ b/services/core/java/com/android/server/textclassifier/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/textclassifier/OWNERS diff --git a/services/core/java/com/android/server/timedetector/OWNERS b/services/core/java/com/android/server/timedetector/OWNERS new file mode 100644 index 000000000000..09447a971bdd --- /dev/null +++ b/services/core/java/com/android/server/timedetector/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/timezone/OWNERS diff --git a/services/core/java/com/android/server/timezone/OWNERS b/services/core/java/com/android/server/timezone/OWNERS new file mode 100644 index 000000000000..09447a971bdd --- /dev/null +++ b/services/core/java/com/android/server/timezone/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/timezone/OWNERS diff --git a/services/core/java/com/android/server/timezonedetector/OWNERS b/services/core/java/com/android/server/timezonedetector/OWNERS new file mode 100644 index 000000000000..09447a971bdd --- /dev/null +++ b/services/core/java/com/android/server/timezonedetector/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/timezone/OWNERS diff --git a/services/core/java/com/android/server/trust/OWNERS b/services/core/java/com/android/server/trust/OWNERS new file mode 100644 index 000000000000..b039c4b45447 --- /dev/null +++ b/services/core/java/com/android/server/trust/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/trust/OWNERS diff --git a/services/core/java/com/android/server/tv/OWNERS b/services/core/java/com/android/server/tv/OWNERS new file mode 100644 index 000000000000..305027ce077f --- /dev/null +++ b/services/core/java/com/android/server/tv/OWNERS @@ -0,0 +1 @@ +include /media/java/android/media/tv/OWNERS diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 1754e593914d..ff5b65b61807 100755 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -77,6 +77,7 @@ import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.UserHandle; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; @@ -100,6 +101,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -329,18 +331,27 @@ public final class TvInputManagerService extends SystemService { userState.packageSet.add(si.packageName); } + // sort the input list by input id so that TvInputState.inputNumber is stable. + Collections.sort(inputList, Comparator.comparing(TvInputInfo::getId)); Map<String, TvInputState> inputMap = new HashMap<>(); + ArrayMap<String, Integer> tisInputCount = new ArrayMap<>(inputMap.size()); for (TvInputInfo info : inputList) { + String inputId = info.getId(); if (DEBUG) { - Slog.d(TAG, "add " + info.getId()); + Slog.d(TAG, "add " + inputId); } - TvInputState inputState = userState.inputMap.get(info.getId()); + // Running count of input for each input service + Integer count = tisInputCount.get(inputId); + count = count == null ? Integer.valueOf(1) : count + 1; + tisInputCount.put(inputId, count); + TvInputState inputState = userState.inputMap.get(inputId); if (inputState == null) { inputState = new TvInputState(); } inputState.info = info; inputState.uid = getInputUid(info); - inputMap.put(info.getId(), inputState); + inputMap.put(inputId, inputState); + inputState.inputNumber = count; } for (String inputId : inputMap.keySet()) { @@ -2452,11 +2463,31 @@ public final class TvInputManagerService extends SystemService { */ private void logTuneStateChanged(int state, SessionState sessionState, @Nullable TvInputState inputState) { - // TODO(b/173536904): log input type and id + int tisUid = Process.INVALID_UID; + int inputType = FrameworkStatsLog.TIF_TUNE_STATE_CHANGED__TYPE__TIF_INPUT_TYPE_UNKNOWN; + int inputId = 0; + int hdmiPort = 0; + if (inputState != null) { + tisUid = inputState.uid; + inputType = inputState.info.getType(); + if (inputType == TvInputInfo.TYPE_TUNER) { + inputType = FrameworkStatsLog.TIF_TUNE_STATE_CHANGED__TYPE__TUNER; + } + inputId = inputState.inputNumber; + HdmiDeviceInfo hdmiDeviceInfo = inputState.info.getHdmiDeviceInfo(); + if (hdmiDeviceInfo != null) { + hdmiPort = hdmiDeviceInfo.getPortId(); + } + } FrameworkStatsLog.write(FrameworkStatsLog.TIF_TUNE_CHANGED, new int[]{sessionState.callingUid, - inputState == null ? Process.INVALID_UID : inputState.uid}, - new String[]{"tif_player", "tv_input_service"}, state, sessionState.sessionId); + tisUid}, + new String[]{"tif_player", "tv_input_service"}, + state, + sessionState.sessionId, + inputType, + inputId, + hdmiPort); } private static final class UserState { @@ -2569,6 +2600,11 @@ public final class TvInputManagerService extends SystemService { private TvInputInfo info; /** + * ID unique to a specific TvInputService. + */ + private int inputNumber; + + /** * The kernel user-ID that has been assigned to the application the TvInput is a part of. * * <p> diff --git a/services/core/java/com/android/server/uri/OWNERS b/services/core/java/com/android/server/uri/OWNERS new file mode 100644 index 000000000000..cdc07ed7c67a --- /dev/null +++ b/services/core/java/com/android/server/uri/OWNERS @@ -0,0 +1,3 @@ +jsharkey@android.com +jsharkey@google.com +varunshah@google.com diff --git a/services/core/java/com/android/server/vibrator/OWNERS b/services/core/java/com/android/server/vibrator/OWNERS new file mode 100644 index 000000000000..7e7335d68d3b --- /dev/null +++ b/services/core/java/com/android/server/vibrator/OWNERS @@ -0,0 +1 @@ +michaelwr@google.com diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java index e2cdd02deab9..b0266d025c08 100644 --- a/services/core/java/com/android/server/vibrator/Vibration.java +++ b/services/core/java/com/android/server/vibrator/Vibration.java @@ -47,7 +47,7 @@ public class Vibration { FINISHED, FORWARDED_TO_INPUT_DEVICES, CANCELLED, - ERROR_APP_OPS, + IGNORED_ERROR_APP_OPS, IGNORED, IGNORED_APP_OPS, IGNORED_BACKGROUND, diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java index 6a5d1c4173c9..a34a50737ec5 100644 --- a/services/core/java/com/android/server/vibrator/VibrationSettings.java +++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java @@ -16,12 +16,18 @@ package com.android.server.vibrator; +import android.app.ActivityManager; +import android.app.IUidObserver; import android.content.Context; import android.content.res.Resources; import android.database.ContentObserver; import android.media.AudioManager; import android.net.Uri; import android.os.Handler; +import android.os.PowerManager; +import android.os.PowerManagerInternal; +import android.os.PowerSaveState; +import android.os.RemoteException; import android.os.UserHandle; import android.os.VibrationAttributes; import android.os.VibrationEffect; @@ -30,7 +36,7 @@ import android.provider.Settings; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; +import com.android.server.LocalServices; import java.util.ArrayList; import java.util.List; @@ -53,6 +59,7 @@ public final class VibrationSettings { private final Vibrator mVibrator; private final AudioManager mAudioManager; private final SettingsObserver mSettingObserver; + private final UidObserver mUidObserver; @GuardedBy("mLock") private final List<OnVibratorSettingsChanged> mListeners = new ArrayList<>(); @@ -72,12 +79,15 @@ public final class VibrationSettings { private int mNotificationIntensity; @GuardedBy("mLock") private int mRingIntensity; + @GuardedBy("mLock") + private boolean mLowPowerMode; public VibrationSettings(Context context, Handler handler) { mContext = context; mVibrator = context.getSystemService(Vibrator.class); mAudioManager = context.getSystemService(AudioManager.class); mSettingObserver = new SettingsObserver(handler); + mUidObserver = new UidObserver(); registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES)); registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING)); @@ -107,6 +117,35 @@ public final class VibrationSettings { mFallbackEffects.put(VibrationEffect.EFFECT_TEXTURE_TICK, VibrationEffect.get(VibrationEffect.EFFECT_TICK, false)); + try { + ActivityManager.getService().registerUidObserver(mUidObserver, + ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE, + ActivityManager.PROCESS_STATE_UNKNOWN, null); + } catch (RemoteException e) { + // ignored; both services live in system_server + } + + PowerManagerInternal pm = LocalServices.getService(PowerManagerInternal.class); + pm.registerLowPowerModeObserver( + new PowerManagerInternal.LowPowerModeListener() { + @Override + public int getServiceType() { + return PowerManager.ServiceType.VIBRATION; + } + + @Override + public void onLowPowerModeChanged(PowerSaveState result) { + boolean shouldNotifyListeners; + synchronized (mLock) { + shouldNotifyListeners = result.batterySaverEnabled != mLowPowerMode; + mLowPowerMode = result.batterySaverEnabled; + } + if (shouldNotifyListeners) { + notifyListeners(); + } + } + }); + // Update with current values from settings. updateSettings(); } @@ -184,12 +223,15 @@ public final class VibrationSettings { } /** - * Return {@code true} if the device should vibrate for ringtones. + * Return {@code true} if the device should vibrate for current ringer mode. * * <p>This checks the current {@link AudioManager#getRingerModeInternal()} against user settings - * for vibrations while ringing. + * for ringtone usage only. All other usages are allowed independently of ringer mode. */ - public boolean shouldVibrateForRingtone() { + public boolean shouldVibrateForRingerMode(int usageHint) { + if (!isRingtone(usageHint)) { + return true; + } int ringerMode = mAudioManager.getRingerModeInternal(); synchronized (mLock) { if (mVibrateWhenRinging) { @@ -202,6 +244,28 @@ public final class VibrationSettings { } } + /** + * Returns {@code true} if this vibration is allowed for given {@code uid}. + * + * <p>This checks if the user is aware of this foreground process, or if the vibration usage is + * allowed to play in the background (i.e. it's a notification, ringtone or alarm vibration). + */ + public boolean shouldVibrateForUid(int uid, int usageHint) { + return mUidObserver.isUidForeground(uid) || isNotification(usageHint) + || isRingtone(usageHint) || isAlarm(usageHint); + } + + /** + * Returns {@code true} if this vibration is allowed for current power mode state. + * + * <p>This checks if the device is in battery saver mode, in which case only alarm, ringtone and + * {@link VibrationAttributes#USAGE_COMMUNICATION_REQUEST} usages are allowed to vibrate. + */ + public boolean shouldVibrateForPowerMode(int usageHint) { + return !mLowPowerMode || isRingtone(usageHint) || isAlarm(usageHint) + || usageHint == VibrationAttributes.USAGE_COMMUNICATION_REQUEST; + } + /** Return {@code true} if input devices should vibrate instead of this device. */ public boolean shouldVibrateInputDevices() { return mVibrateInputDevices; @@ -229,9 +293,7 @@ public final class VibrationSettings { } /** Updates all vibration settings and triggers registered listeners. */ - @VisibleForTesting public void updateSettings() { - List<OnVibratorSettingsChanged> currentListeners; synchronized (mLock) { mVibrateWhenRinging = getSystemSetting(Settings.System.VIBRATE_WHEN_RINGING, 0) != 0; mApplyRampingRinger = getGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0) != 0; @@ -244,12 +306,8 @@ public final class VibrationSettings { mVibrator.getDefaultRingVibrationIntensity()); mVibrateInputDevices = getSystemSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0) > 0; mZenMode = getGlobalSetting(Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF); - currentListeners = new ArrayList<>(mListeners); - } - - for (OnVibratorSettingsChanged listener : currentListeners) { - listener.onChange(); } + notifyListeners(); } @Override @@ -258,9 +316,11 @@ public final class VibrationSettings { + "mVibrateInputDevices=" + mVibrateInputDevices + ", mVibrateWhenRinging=" + mVibrateWhenRinging + ", mApplyRampingRinger=" + mApplyRampingRinger + + ", mLowPowerMode=" + mLowPowerMode + ", mZenMode=" + Settings.Global.zenModeToString(mZenMode) + + ", mProcStatesCache=" + mUidObserver.mProcStatesCache + ", mHapticFeedbackIntensity=" - + intensityToString(getCurrentIntensity(VibrationAttributes.USAGE_TOUCH)) + + intensityToString(getCurrentIntensity(VibrationAttributes.USAGE_TOUCH)) + ", mHapticFeedbackDefaultIntensity=" + intensityToString(getDefaultIntensity(VibrationAttributes.USAGE_TOUCH)) + ", mNotificationIntensity=" @@ -274,6 +334,16 @@ public final class VibrationSettings { + '}'; } + private void notifyListeners() { + List<OnVibratorSettingsChanged> currentListeners; + synchronized (mLock) { + currentListeners = new ArrayList<>(mListeners); + } + for (OnVibratorSettingsChanged listener : currentListeners) { + listener.onChange(); + } + } + private static String intensityToString(int intensity) { switch (intensity) { case Vibrator.VIBRATION_INTENSITY_OFF: @@ -342,4 +412,36 @@ public final class VibrationSettings { updateSettings(); } } + + /** Implementation of {@link ContentObserver} to be registered to a setting {@link Uri}. */ + private final class UidObserver extends IUidObserver.Stub { + private final SparseArray<Integer> mProcStatesCache = new SparseArray<>(); + + public boolean isUidForeground(int uid) { + return mProcStatesCache.get(uid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) + <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + } + + @Override + public void onUidGone(int uid, boolean disabled) { + mProcStatesCache.delete(uid); + } + + @Override + public void onUidActive(int uid) { + } + + @Override + public void onUidIdle(int uid, boolean disabled) { + } + + @Override + public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { + mProcStatesCache.put(uid, procState); + } + + @Override + public void onUidCachedChanged(int uid, boolean cached) { + } + } } diff --git a/services/core/java/com/android/server/vibrator/VibratorController.java b/services/core/java/com/android/server/vibrator/VibratorController.java index f76c1a1b2b9d..311c73bcb19f 100644 --- a/services/core/java/com/android/server/vibrator/VibratorController.java +++ b/services/core/java/com/android/server/vibrator/VibratorController.java @@ -23,7 +23,7 @@ import android.os.IVibratorStateListener; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.VibrationEffect; -import android.os.Vibrator; +import android.os.VibratorInfo; import android.util.Slog; import com.android.internal.annotations.GuardedBy; @@ -31,10 +31,6 @@ import com.android.internal.annotations.VisibleForTesting; import libcore.util.NativeAllocationRegistry; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - /** Controls a single vibrator. */ // TODO(b/159207608): Make this package-private once vibrator services are moved to this package public final class VibratorController { @@ -42,12 +38,7 @@ public final class VibratorController { private final Object mLock = new Object(); private final NativeWrapper mNativeWrapper; - private final int mVibratorId; - private final long mCapabilities; - @Nullable - private final Set<Integer> mSupportedEffects; - @Nullable - private final Set<Integer> mSupportedPrimitives; + private final VibratorInfo mVibratorInfo; @GuardedBy("mLock") private final RemoteCallbackList<IVibratorStateListener> mVibratorStateListeners = @@ -115,13 +106,11 @@ public final class VibratorController { @VisibleForTesting public VibratorController(int vibratorId, OnVibrationCompleteListener listener, NativeWrapper nativeWrapper) { - mVibratorId = vibratorId; mNativeWrapper = nativeWrapper; + mNativeWrapper.init(vibratorId, listener); - nativeWrapper.init(vibratorId, listener); - mCapabilities = nativeWrapper.getCapabilities(); - mSupportedEffects = asSet(nativeWrapper.getSupportedEffects()); - mSupportedPrimitives = asSet(nativeWrapper.getSupportedPrimitives()); + mVibratorInfo = new VibratorInfo(vibratorId, nativeWrapper.getCapabilities(), + nativeWrapper.getSupportedEffects(), nativeWrapper.getSupportedPrimitives()); } /** Register state listener for this vibrator. */ @@ -153,9 +142,9 @@ public final class VibratorController { } } - /** Return the id of the vibrator controlled by this instance. */ - public int getVibratorId() { - return mVibratorId; + /** Return the {@link VibratorInfo} representing the vibrator controlled by this instance. */ + public VibratorInfo getVibratorInfo() { + return mVibratorInfo; } /** @@ -184,43 +173,7 @@ public final class VibratorController { * @return true if this vibrator has this capability, false otherwise */ public boolean hasCapability(long capability) { - return (mCapabilities & capability) == capability; - } - - /** - * Check against this vibrator supported effects. - * - * @param effectIds list of effects, one of VibrationEffect.EFFECT_* - * @return one entry per requested effectId, with one of Vibrator.VIBRATION_EFFECT_SUPPORT_* - */ - public int[] areEffectsSupported(int[] effectIds) { - int[] supported = new int[effectIds.length]; - if (mSupportedEffects == null) { - Arrays.fill(supported, Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN); - } else { - for (int i = 0; i < effectIds.length; i++) { - supported[i] = mSupportedEffects.contains(effectIds[i]) - ? Vibrator.VIBRATION_EFFECT_SUPPORT_YES - : Vibrator.VIBRATION_EFFECT_SUPPORT_NO; - } - } - return supported; - } - - /** - * Check against this vibrator supported primitives. - * - * @param primitiveIds list of primitives, one of VibrationEffect.Composition.EFFECT_* - * @return one entry per requested primitiveId, with true if it is supported - */ - public boolean[] arePrimitivesSupported(int[] primitiveIds) { - boolean[] supported = new boolean[primitiveIds.length]; - if (mSupportedPrimitives != null && hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { - for (int i = 0; i < primitiveIds.length; i++) { - supported[i] = mSupportedPrimitives.contains(primitiveIds[i]); - } - } - return supported; + return mVibratorInfo.hasCapability(capability); } /** Return {@code true} if the underlying vibrator is currently available, false otherwise. */ @@ -234,7 +187,7 @@ public final class VibratorController { * <p>This will affect the state of {@link #isUnderExternalControl()}. */ public void setExternalControl(boolean externalControl) { - if (!hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) { + if (!mVibratorInfo.hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) { return; } synchronized (mLock) { @@ -248,7 +201,7 @@ public final class VibratorController { * if given {@code effect} is {@code null}. */ public void updateAlwaysOn(int id, @Nullable VibrationEffect.Prebaked effect) { - if (!hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { + if (!mVibratorInfo.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { return; } synchronized (mLock) { @@ -263,7 +216,7 @@ public final class VibratorController { /** Set the vibration amplitude. This will NOT affect the state of {@link #isVibrating()}. */ public void setAmplitude(int amplitude) { synchronized (mLock) { - if (hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) { + if (mVibratorInfo.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) { mNativeWrapper.setAmplitude(amplitude); } } @@ -306,7 +259,7 @@ public final class VibratorController { * <p>This will affect the state of {@link #isVibrating()}. */ public void on(VibrationEffect.Composed effect, long vibrationId) { - if (!hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { + if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { return; } synchronized (mLock) { @@ -327,10 +280,7 @@ public final class VibratorController { @Override public String toString() { return "VibratorController{" - + "mVibratorId=" + mVibratorId - + ", mCapabilities=" + mCapabilities - + ", mSupportedEffects=" + mSupportedEffects - + ", mSupportedPrimitives=" + mSupportedPrimitives + + "mVibratorInfo=" + mVibratorInfo + ", mIsVibrating=" + mIsVibrating + ", mIsUnderExternalControl=" + mIsUnderExternalControl + ", mVibratorStateListeners count=" @@ -375,18 +325,6 @@ public final class VibratorController { } } - @Nullable - private static Set<Integer> asSet(int[] values) { - if (values == null) { - return null; - } - HashSet<Integer> set = new HashSet<>(); - for (int value : values) { - set.add(value); - } - return set; - } - /** Wrapper around the static-native methods of {@link VibratorController} for tests. */ @VisibleForTesting public static class NativeWrapper { diff --git a/services/core/java/com/android/server/wallpaper/IWallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/IWallpaperManagerService.java index 60b08dd3093c..a4ddf1170fe6 100644 --- a/services/core/java/com/android/server/wallpaper/IWallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/IWallpaperManagerService.java @@ -29,7 +29,7 @@ interface IWallpaperManagerService extends IWallpaperManager, IBinder { void onBootPhase(int phase); /** - * @see com.android.server.SystemService#onUnlockUser(int) + * @see com.android.server.SystemService#onUserUnlocking */ void onUnlockUser(final int userId); }
\ No newline at end of file diff --git a/services/core/java/com/android/server/wallpaper/OWNERS b/services/core/java/com/android/server/wallpaper/OWNERS new file mode 100644 index 000000000000..8ff0f74202f8 --- /dev/null +++ b/services/core/java/com/android/server/wallpaper/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/wallpaper/OWNERS diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java index 9f1152c8e371..85fcd3dbe501 100644 --- a/services/core/java/com/android/server/wm/ActivityClientController.java +++ b/services/core/java/com/android/server/wm/ActivityClientController.java @@ -538,6 +538,22 @@ class ActivityClientController extends IActivityClientController.Stub { } @Override + public int getLaunchedFromUid(IBinder token) { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.forTokenLocked(token); + return r != null ? r.launchedFromUid : android.os.Process.INVALID_UID; + } + } + + @Override + public String getLaunchedFromPackage(IBinder token) { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.forTokenLocked(token); + return r != null ? r.launchedFromPackage : null; + } + } + + @Override public Bundle getActivityOptions(IBinder token) { final long origId = Binder.clearCallingIdentity(); try { diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 743796b0aad0..113f4d856bdd 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1366,7 +1366,19 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } else if (mLetterbox != null) { mLetterbox.hide(); } - task.maybeUpdateLetterboxBounds(this, getLetterboxParams(w)); + maybeUpdateLetterboxInTaskOrganizer(w); + } + + private void maybeUpdateLetterboxInTaskOrganizer(WindowState w) { + boolean isLetterboxed = w.isLetterboxedAppWindow() && fillsParent(); + if (!isLetterboxed) { + task.maybeUpdateLetterboxInTaskOrganizer( + this, /* activityBounds= */ null, /* activityInsets= */ null); + return; + } + final Rect insets = w.getInsetsStateWithVisibilityOverride().calculateInsets( + getBounds(), Type.systemBars(), false /* ignoreVisibility */); + task.maybeUpdateLetterboxInTaskOrganizer(this, getBounds(), insets); } void updateLetterboxSurface(WindowState winHint) { @@ -1380,12 +1392,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } } - @Nullable - private Rect getLetterboxParams(WindowState w) { - boolean isLetterboxed = w.isLetterboxedAppWindow() && fillsParent(); - return isLetterboxed ? getBounds() : null; - } - Rect getLetterboxInsets() { if (mLetterbox != null) { return mLetterbox.getInsets(); diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index a5df2a604808..f8b3c1ba856f 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -386,6 +386,10 @@ public abstract class ActivityTaskManagerInternal { public abstract void clearPendingResultForActivity( IBinder activityToken, WeakReference<PendingIntentRecord> pir); + /** Returns the component name of the activity token. */ + @Nullable + public abstract ComponentName getActivityName(IBinder activityToken); + /** * @return the activity token and IApplicationThread for the top activity in the task or null * if there isn't a top activity with a valid process. diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 8298dfd85114..9e7ddbaeb434 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -1743,29 +1743,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } - @Override - public int getLaunchedFromUid(IBinder activityToken) { - ActivityRecord srec; - synchronized (mGlobalLock) { - srec = ActivityRecord.forTokenLocked(activityToken); - } - if (srec == null) { - return -1; - } - return srec.launchedFromUid; - } - - @Override - public String getLaunchedFromPackage(IBinder activityToken) { - ActivityRecord srec; - synchronized (mGlobalLock) { - srec = ActivityRecord.forTokenLocked(activityToken); - } - if (srec == null) { - return null; - } - return srec.launchedFromPackage; - } @Override public RootTaskInfo getFocusedRootTaskInfo() throws RemoteException { @@ -3228,28 +3205,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public ComponentName getActivityClassForToken(IBinder token) { - synchronized (mGlobalLock) { - ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return null; - } - return r.intent.getComponent(); - } - } - - @Override - public String getPackageForToken(IBinder token) { - synchronized (mGlobalLock) { - ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return null; - } - return r.packageName; - } - } - - @Override public void keyguardGoingAway(int flags) { enforceNotIsolatedCaller("keyguardGoingAway"); final long token = Binder.clearCallingIdentity(); @@ -4708,8 +4663,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { .setContentTitle(text) .setContentText( mContext.getText(R.string.heavy_weight_notification_detail)) + // TODO(b/175194709) Please replace FLAG_MUTABLE_UNAUDITED below + // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0, - intent, PendingIntent.FLAG_CANCEL_CURRENT, null, + intent, PendingIntent.FLAG_CANCEL_CURRENT + | PendingIntent.FLAG_MUTABLE_UNAUDITED, null, new UserHandle(userId))) .build(); try { @@ -5596,6 +5554,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override + public ComponentName getActivityName(IBinder activityToken) { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(activityToken); + return r != null ? r.intent.getComponent() : null; + } + } + + @Override public ActivityTokens getTopActivityForTask(int taskId) { synchronized (mGlobalLock) { final Task task = mRootWindowContainer.anyTaskForId(taskId); diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 73d99724c65f..370ee265bc00 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -88,6 +88,7 @@ import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityOptions; import android.app.AppOpsManager; +import android.app.IActivityClientController; import android.app.ProfilerInfo; import android.app.ResultInfo; import android.app.WaitResult; @@ -795,6 +796,11 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { + " old=" + r.app + " new=" + proc); } + // Send the controller to client if the process is the first time to launch activity. + // So the client can save binder transactions of getting the controller from activity + // task manager service. + final IActivityClientController activityClientController = + proc.hasEverLaunchedActivity() ? null : mService.mActivityClientController; r.launchCount++; r.lastLaunchTime = SystemClock.uptimeMillis(); proc.setLastActivityLaunchTime(r.lastLaunchTime); @@ -863,7 +869,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(), results, newIntents, dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(), - r.assistToken, r.createFixedRotationAdjustmentsIfNeeded())); + r.assistToken, activityClientController, + r.createFixedRotationAdjustmentsIfNeeded())); // Set desired final state. final ActivityLifecycleItem lifecycleItem; diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java index d4b319a525da..f8c375497b7b 100644 --- a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java @@ -99,23 +99,41 @@ public abstract class DisplayAreaPolicy { // Define the features that will be supported under the root of the whole logical // display. The policy will build the DisplayArea hierarchy based on this. - HierarchyBuilder rootHierarchy = new HierarchyBuilder(root) - // WindowedMagnification should be on the top so that there is only one surface - // to be magnified. - .addFeature(new Feature.Builder(wmService.mPolicy, "WindowedMagnification", - FEATURE_WINDOWED_MAGNIFICATION) - .upTo(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY) - .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY) - // Make the DA dimmable so that the magnify window also mirrors the dim - // layer - .setNewDisplayAreaSupplier(DisplayArea.Dimmable::new) - .build()) - .addFeature(new Feature.Builder(wmService.mPolicy, "HideDisplayCutout", - FEATURE_HIDE_DISPLAY_CUTOUT) - .all() - .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL, TYPE_STATUS_BAR, - TYPE_NOTIFICATION_SHADE) - .build()) + final HierarchyBuilder rootHierarchy = new HierarchyBuilder(root); + if (content.isTrusted()) { + // Only trusted display can have system decorations. + configureTrustedHierarchyBuilder(rootHierarchy, wmService, content); + } + // Set the essential containers (even the display doesn't support IME). + rootHierarchy.setImeContainer(imeContainer).setTaskDisplayAreas(tdaList); + + // Instantiate the policy with the hierarchy defined above. This will create and attach + // all the necessary DisplayAreas to the root. + return new DisplayAreaPolicyBuilder().setRootHierarchy(rootHierarchy).build(wmService); + } + + private void configureTrustedHierarchyBuilder(HierarchyBuilder rootHierarchy, + WindowManagerService wmService, DisplayContent content) { + // WindowedMagnification should be on the top so that there is only one surface + // to be magnified. + rootHierarchy.addFeature(new Feature.Builder(wmService.mPolicy, "WindowedMagnification", + FEATURE_WINDOWED_MAGNIFICATION) + .upTo(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY) + .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY) + // Make the DA dimmable so that the magnify window also mirrors the dim layer. + .setNewDisplayAreaSupplier(DisplayArea.Dimmable::new) + .build()); + if (content.isDefaultDisplay) { + // Only default display can have cutout. + // See LocalDisplayAdapter.LocalDisplayDevice#getDisplayDeviceInfoLocked. + rootHierarchy.addFeature(new Feature.Builder(wmService.mPolicy, "HideDisplayCutout", + FEATURE_HIDE_DISPLAY_CUTOUT) + .all() + .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL, + TYPE_STATUS_BAR, TYPE_NOTIFICATION_SHADE) + .build()); + } + rootHierarchy .addFeature(new Feature.Builder(wmService.mPolicy, "OneHanded", FEATURE_ONE_HANDED) .all() @@ -131,13 +149,7 @@ public abstract class DisplayAreaPolicy { .addFeature(new Feature.Builder(wmService.mPolicy, "ImePlaceholder", FEATURE_IME_PLACEHOLDER) .and(TYPE_INPUT_METHOD, TYPE_INPUT_METHOD_DIALOG) - .build()) - .setImeContainer(imeContainer) - .setTaskDisplayAreas(tdaList); - - // Instantiate the policy with the hierarchy defined above. This will create and attach - // all the necessary DisplayAreas to the root. - return new DisplayAreaPolicyBuilder().setRootHierarchy(rootHierarchy).build(wmService); + .build()); } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index e88f8e390833..0678a5e4383b 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -2298,10 +2298,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp .setSubtype(getConfiguration().orientation) .addTaggedData(MetricsEvent.FIELD_DISPLAY_ID, getDisplayId())); } - - if (mPinnedStackControllerLocked != null) { - mPinnedStackControllerLocked.onDisplayInfoChanged(getDisplayInfo()); - } } /** diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java index fd42b2467d19..8fe2481f9eda 100644 --- a/services/core/java/com/android/server/wm/PinnedStackController.java +++ b/services/core/java/com/android/server/wm/PinnedStackController.java @@ -127,7 +127,6 @@ class PinnedStackController { try { listener.asBinder().linkToDeath(mPinnedStackListenerDeathHandler, 0); mPinnedStackListener = listener; - notifyDisplayInfoChanged(mDisplayInfo); notifyImeVisibilityChanged(mIsImeShowing, mImeHeight); notifyMovementBoundsChanged(false /* fromImeAdjustment */); notifyActionsChanged(mActions); @@ -171,23 +170,6 @@ class PinnedStackController { } } - private void setDisplayInfo(DisplayInfo displayInfo) { - mDisplayInfo.copyFrom(displayInfo); - notifyDisplayInfoChanged(mDisplayInfo); - } - - /** - * In the case where the display rotation is changed but there is no stack, we can't depend on - * onTaskStackBoundsChanged() to be called. But we still should update our known display info - * with the new state so that we can update SystemUI. - */ - void onDisplayInfoChanged(DisplayInfo displayInfo) { - synchronized (mService.mGlobalLock) { - setDisplayInfo(displayInfo); - notifyMovementBoundsChanged(false /* fromImeAdjustment */); - } - } - /** * Sets the Ime state and height. */ @@ -288,18 +270,6 @@ class PinnedStackController { } } - /** - * Notifies listeners that the PIP animation is about to happen. - */ - private void notifyDisplayInfoChanged(DisplayInfo displayInfo) { - if (mPinnedStackListener == null) return; - try { - mPinnedStackListener.onDisplayInfoChanged(displayInfo); - } catch (RemoteException e) { - Slog.e(TAG_WM, "Error delivering DisplayInfo changed event.", e); - } - } - void dump(String prefix, PrintWriter pw) { pw.println(prefix + "PinnedStackController"); pw.println(prefix + " mIsImeShowing=" + mIsImeShowing); diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 5da668c8c361..128c259926c7 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -763,7 +763,7 @@ public class RecentsAnimationController implements DeathRecipient { taskAdapter.mTask.dontAnimateDimExit(); } removeAnimation(taskAdapter); - taskAdapter.maybeApplyFinishBounds(); + taskAdapter.onCleanup(); } for (int i = mPendingWallpaperAnimations.size() - 1; i >= 0; i--) { @@ -850,7 +850,7 @@ public class RecentsAnimationController implements DeathRecipient { return w != null && w.mAttrs.type == TYPE_BASE_APPLICATION && ((w.mActivityRecord != null && mTargetActivityRecord == w.mActivityRecord) || isAnimatingTask(w.getTask())) - && isTargetOverWallpaper(); + && isTargetOverWallpaper() && w.isOnScreen(); } /** @@ -987,14 +987,19 @@ public class RecentsAnimationController implements DeathRecipient { return mTarget; } - void maybeApplyFinishBounds() { + void onCleanup() { if (!mFinishBounds.isEmpty()) { + // Apply any pending bounds changes final SurfaceControl taskSurface = mTask.getSurfaceControl(); mTask.getPendingTransaction() .setPosition(taskSurface, mFinishBounds.left, mFinishBounds.top) .setWindowCrop(taskSurface, mFinishBounds.width(), mFinishBounds.height()) .apply(); mFinishBounds.setEmpty(); + } else { + // Apply the task's pending transaction in case it is detached and its transaction + // is not reachable. + mTask.getPendingTransaction().apply(); } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 4b65ce0f7088..8564cbc02df8 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -224,7 +224,6 @@ import com.android.server.uri.NeededUriGrants; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; import java.io.FileDescriptor; import java.io.IOException; @@ -520,6 +519,11 @@ class Task extends WindowContainer<WindowContainer> { @Nullable private Rect mLetterboxActivityBounds; + // Activity insets if this task or its top activity is presented in letterbox mode and + // {@code null} otherwise. + @Nullable + private Rect mLetterboxActivityInsets; + // Whether the task is currently being drag-resized private boolean mDragResizing; private int mDragResizeMode; @@ -4084,6 +4088,7 @@ class Task extends WindowContainer<WindowContainer> { // bounds, e.g. fullscreen bounds instead of letterboxed bounds. To work around this, // assigning bounds from ActivityRecord#layoutLetterbox when they are ready. info.letterboxActivityBounds = Rect.copyOrNull(mLetterboxActivityBounds); + info.letterboxActivityInsets = Rect.copyOrNull(mLetterboxActivityInsets); info.positionInParent = getRelativePosition(); info.parentBounds = getParentBounds(); @@ -4108,18 +4113,20 @@ class Task extends WindowContainer<WindowContainer> { if (top == null) return null; final ActivityRecord rootActivity = top.getRootActivity(); return (rootActivity == null || rootActivity.pictureInPictureArgs.empty()) - ? null : rootActivity.pictureInPictureArgs; + ? null : new PictureInPictureParams(rootActivity.pictureInPictureArgs); } - void maybeUpdateLetterboxBounds( - ActivityRecord activityRecord, @Nullable Rect letterboxActivityBounds) { + void maybeUpdateLetterboxInTaskOrganizer( + ActivityRecord activityRecord, + @Nullable Rect activityBounds, + @Nullable Rect activityInsets) { if (isOrganized() && mReuseActivitiesReport.top == activityRecord // Want to force update only if letterbox bounds have changed. - && !Objects.equals( - mLetterboxActivityBounds, - letterboxActivityBounds)) { - mLetterboxActivityBounds = Rect.copyOrNull(letterboxActivityBounds); + && (!Objects.equals(mLetterboxActivityBounds, activityBounds) + || !Objects.equals(mLetterboxActivityInsets, activityInsets))) { + mLetterboxActivityBounds = Rect.copyOrNull(activityBounds); + mLetterboxActivityInsets = Rect.copyOrNull(activityInsets); // Forcing update to reduce visual jank during the transition. dispatchTaskInfoChangedIfNeeded(true /* force */); } diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index e635219bc6e5..2095d1925e4b 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -272,7 +272,9 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { void removeTask(Task t) { if (t.mTaskAppearedSent) { - t.migrateToNewSurfaceControl(); + if (t.getSurfaceControl() != null) { + t.migrateToNewSurfaceControl(); + } t.mTaskAppearedSent = false; mOrganizer.onTaskVanished(t); } @@ -288,8 +290,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { // possible. while (!mOrganizedTasks.isEmpty()) { final Task t = mOrganizedTasks.get(0); - t.updateTaskOrganizerState(true /* forceUpdate */); - if (mOrganizedTasks.contains(t)) { + if (!t.updateTaskOrganizerState(true /* forceUpdate */)) { removeTask(t); } } diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java index 616a789b325b..b2f30628f62f 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotController.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java @@ -369,7 +369,8 @@ class TaskSnapshotController { SurfaceControl[] excludeLayers; final WindowState imeWindow = task.getDisplayContent().mInputMethodWindow; // Exclude IME window snapshot when IME isn't proper to attach to app. - if (imeWindow != null && !task.getDisplayContent().isImeAttachedToApp()) { + if (imeWindow != null && imeWindow.getSurfaceControl() != null + && !task.getDisplayContent().isImeAttachedToApp()) { excludeLayers = new SurfaceControl[1]; excludeLayers[0] = imeWindow.getSurfaceControl(); } else { diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index 8f8fea34e620..f3fa978f35dc 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -463,6 +463,10 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio return mUsingWrapper; } + boolean hasEverLaunchedActivity() { + return mLastActivityLaunchTime > 0; + } + void setLastActivityLaunchTime(long launchTime) { if (launchTime <= mLastActivityLaunchTime) { if (launchTime < mLastActivityLaunchTime) { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index c318fad4d0a0..bc8699e2ee39 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -770,6 +770,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } mPendingSeamlessRotate = new SeamlessRotator(oldRotation, rotation, getDisplayInfo(), false /* applyFixedTransformationHint */); + // The surface position is going to be unrotated according to the last position. + // Make sure the source position is up-to-date. + mLastSurfacePosition.set(mSurfacePosition.x, mSurfacePosition.y); mPendingSeamlessRotate.unrotate(transaction, this); getDisplayContent().getDisplayRotation().markForSeamlessRotation(this, true /* seamlesslyRotated */); diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS index 6f74885b98e5..7fc55656fc80 100644 --- a/services/core/jni/OWNERS +++ b/services/core/jni/OWNERS @@ -12,3 +12,18 @@ per-file com_android_server_input_InputManagerService.cpp = michaelwr@google.com per-file com_android_server_HardwarePropertiesManagerService.cpp = michaelwr@google.com, santoscordon@google.com per-file com_android_server_power_PowerManagerService.* = michaelwr@google.com, santoscordon@google.com +per-file Android.bp = file:platform/build/soong:/OWNERS +per-file com_android_server_Usb* = file:/services/usb/OWNERS +per-file com_android_server_Vibrator* = file:/services/core/java/com/android/server/vibrator/OWNERS +per-file com_android_server_hdmi_* = file:/core/java/android/hardware/hdmi/OWNERS +per-file com_android_server_input_* = file:/core/java/android/hardware/input/OWNERS +per-file com_android_server_lights_* = file:/services/core/java/com/android/server/lights/OWNERS +per-file com_android_server_location_* = file:/location/java/android/location/OWNERS +per-file com_android_server_locksettings_* = file:/services/core/java/com/android/server/locksettings/OWNERS +per-file com_android_server_net_* = file:/services/core/java/com/android/server/net/OWNERS +per-file com_android_server_pm_* = file:/services/core/java/com/android/server/pm/OWNERS +per-file com_android_server_power_* = file:/services/core/java/com/android/server/power/OWNERS +per-file com_android_server_se_* = file:/core/java/android/se/OWNERS +per-file com_android_server_security_* = file:/core/java/android/security/OWNERS +per-file com_android_server_tv_* = file:/media/java/android/media/tv/OWNERS +per-file com_android_server_vibrator_* = file:/services/core/java/com/android/server/vibrator/OWNERS diff --git a/services/core/jni/com_android_server_VibratorManagerService.cpp b/services/core/jni/com_android_server_VibratorManagerService.cpp index dae9cefdd1f4..71de9bda3c4f 100644 --- a/services/core/jni/com_android_server_VibratorManagerService.cpp +++ b/services/core/jni/com_android_server_VibratorManagerService.cpp @@ -26,8 +26,13 @@ #include <vibratorservice/VibratorManagerHalWrapper.h> +#include "com_android_server_VibratorManagerService.h" + namespace android { +static std::mutex gManagerMutex; +static vibrator::ManagerHalWrapper* gManager GUARDED_BY(gManagerMutex) = nullptr; + class NativeVibratorManagerService { public: NativeVibratorManagerService() : mHal(std::make_unique<vibrator::LegacyManagerHalWrapper>()) {} @@ -39,9 +44,16 @@ private: const std::unique_ptr<vibrator::ManagerHalWrapper> mHal; }; +vibrator::ManagerHalWrapper* android_server_VibratorManagerService_getManager() { + std::lock_guard<std::mutex> lock(gManagerMutex); + return gManager; +} + static void destroyNativeService(void* ptr) { NativeVibratorManagerService* service = reinterpret_cast<NativeVibratorManagerService*>(ptr); if (service) { + std::lock_guard<std::mutex> lock(gManagerMutex); + gManager = nullptr; delete service; } } @@ -49,6 +61,10 @@ static void destroyNativeService(void* ptr) { static jlong nativeInit(JNIEnv* /* env */, jclass /* clazz */) { std::unique_ptr<NativeVibratorManagerService> service = std::make_unique<NativeVibratorManagerService>(); + { + std::lock_guard<std::mutex> lock(gManagerMutex); + gManager = service->hal(); + } return reinterpret_cast<jlong>(service.release()); } diff --git a/services/core/jni/com_android_server_VibratorManagerService.h b/services/core/jni/com_android_server_VibratorManagerService.h new file mode 100644 index 000000000000..3f2a322b19ee --- /dev/null +++ b/services/core/jni/com_android_server_VibratorManagerService.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _ANDROID_SERVER_VIBRATOR_MANAGER_SERVICE_H +#define _ANDROID_SERVER_VIBRATOR_MANAGER_SERVICE_H + +#include <vibratorservice/VibratorManagerHalWrapper.h> + +namespace android { + +extern vibrator::ManagerHalWrapper* android_server_VibratorManagerService_getManager(); + +} // namespace android + +#endif // _ANDROID_SERVER_VIBRATOR_MANAGER_SERVICE_H diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 13450be73d88..404b182d968f 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -149,6 +149,14 @@ static struct { jmethodID getAffineTransform; } gTouchCalibrationClassInfo; +static struct { + jclass clazz; + jmethodID constructor; + jmethodID keyAt; + jmethodID valueAt; + jmethodID size; +} gSparseArrayClassInfo; + // --- Global functions --- template<typename T> @@ -1705,19 +1713,73 @@ static void nativeVibrate(JNIEnv* env, jclass /* clazz */, jlong ptr, jint devic patternObj, nullptr)); jint* amplitudes = static_cast<jint*>(env->GetPrimitiveArrayCritical(amplitudesObj, nullptr)); - std::vector<VibrationElement> elements(patternSize); + VibrationSequence sequence(patternSize); + std::vector<int32_t> vibrators = im->getInputManager()->getReader()->getVibratorIds(deviceId); for (size_t i = 0; i < patternSize; i++) { // VibrationEffect.validate guarantees duration > 0. std::chrono::milliseconds duration(patternMillis[i]); - elements[i].duration = std::min(duration, MAX_VIBRATE_PATTERN_DELAY_MILLIS); - // TODO: (b/161629089) apply channel specific amplitudes from development API. - elements[i].channels = {static_cast<uint8_t>(amplitudes[i]), - static_cast<uint8_t>(amplitudes[i])}; + VibrationElement element(CHANNEL_SIZE); + element.duration = std::min(duration, MAX_VIBRATE_PATTERN_DELAY_MILLIS); + // Vibrate on both channels + for (int32_t channel = 0; channel < vibrators.size(); channel++) { + element.addChannel(vibrators[channel], static_cast<uint8_t>(amplitudes[i])); + } + sequence.addElement(element); } env->ReleasePrimitiveArrayCritical(patternObj, patternMillis, JNI_ABORT); env->ReleasePrimitiveArrayCritical(amplitudesObj, amplitudes, JNI_ABORT); - im->getInputManager()->getReader()->vibrate(deviceId, elements, repeat, token); + im->getInputManager()->getReader()->vibrate(deviceId, sequence, repeat, token); +} + +static void nativeVibrateCombined(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId, + jlongArray patternObj, jobject amplitudesObj, jint repeat, + jint token) { + NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); + + size_t patternSize = env->GetArrayLength(patternObj); + + if (patternSize > MAX_VIBRATE_PATTERN_SIZE) { + ALOGI("Skipped requested vibration because the pattern size is %zu " + "which is more than the maximum supported size of %d.", + patternSize, MAX_VIBRATE_PATTERN_SIZE); + return; // limit to reasonable size + } + const jlong* patternMillis = env->GetLongArrayElements(patternObj, nullptr); + + std::array<jint*, CHANNEL_SIZE> amplitudesArray; + std::array<jint, CHANNEL_SIZE> vibratorIdArray; + jint amplSize = env->CallIntMethod(amplitudesObj, gSparseArrayClassInfo.size); + if (amplSize > CHANNEL_SIZE) { + ALOGE("Can not fit into input device vibration element."); + return; + } + + for (int i = 0; i < amplSize; i++) { + vibratorIdArray[i] = env->CallIntMethod(amplitudesObj, gSparseArrayClassInfo.keyAt, i); + jintArray arr = static_cast<jintArray>( + env->CallObjectMethod(amplitudesObj, gSparseArrayClassInfo.valueAt, i)); + amplitudesArray[i] = env->GetIntArrayElements(arr, nullptr); + if (env->GetArrayLength(arr) != patternSize) { + ALOGE("Amplitude length not equal to pattern length!"); + return; + } + } + + VibrationSequence sequence(patternSize); + for (size_t i = 0; i < patternSize; i++) { + VibrationElement element(CHANNEL_SIZE); + // VibrationEffect.validate guarantees duration > 0. + std::chrono::milliseconds duration(patternMillis[i]); + element.duration = std::min(duration, MAX_VIBRATE_PATTERN_DELAY_MILLIS); + for (int32_t channel = 0; channel < CHANNEL_SIZE; channel++) { + element.addChannel(vibratorIdArray[channel], + static_cast<uint8_t>(amplitudesArray[channel][i])); + } + sequence.addElement(element); + } + + im->getInputManager()->getReader()->vibrate(deviceId, sequence, repeat, token); } static void nativeCancelVibrate(JNIEnv* /* env */, @@ -1727,6 +1789,23 @@ static void nativeCancelVibrate(JNIEnv* /* env */, im->getInputManager()->getReader()->cancelVibrate(deviceId, token); } +static bool nativeIsVibrating(JNIEnv* /* env */, jclass /* clazz */, jlong ptr, jint deviceId) { + NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); + + return im->getInputManager()->getReader()->isVibrating(deviceId); +} + +static jintArray nativeGetVibratorIds(JNIEnv* env, jclass clazz, jlong ptr, jint deviceId) { + NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); + std::vector<int32_t> vibrators = im->getInputManager()->getReader()->getVibratorIds(deviceId); + + jintArray vibIdArray = env->NewIntArray(vibrators.size()); + if (vibIdArray != nullptr) { + env->SetIntArrayRegion(vibIdArray, 0, vibrators.size(), vibrators.data()); + } + return vibIdArray; +} + static void nativeReloadKeyboardLayouts(JNIEnv* /* env */, jclass /* clazz */, jlong ptr) { NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); @@ -1872,7 +1951,11 @@ static const JNINativeMethod gInputManagerMethods[] = { {"nativeSetInteractive", "(JZ)V", (void*)nativeSetInteractive}, {"nativeReloadCalibration", "(J)V", (void*)nativeReloadCalibration}, {"nativeVibrate", "(JI[J[III)V", (void*)nativeVibrate}, + {"nativeVibrateCombined", "(JI[JLandroid/util/SparseArray;II)V", + (void*)nativeVibrateCombined}, {"nativeCancelVibrate", "(JII)V", (void*)nativeCancelVibrate}, + {"nativeIsVibrating", "(JI)Z", (void*)nativeIsVibrating}, + {"nativeGetVibratorIds", "(JI)[I", (void*)nativeGetVibratorIds}, {"nativeReloadKeyboardLayouts", "(J)V", (void*)nativeReloadKeyboardLayouts}, {"nativeReloadDeviceAliases", "(J)V", (void*)nativeReloadDeviceAliases}, {"nativeDump", "(J)Ljava/lang/String;", (void*)nativeDump}, @@ -2048,6 +2131,15 @@ int register_android_server_InputManager(JNIEnv* env) { GET_METHOD_ID(gTouchCalibrationClassInfo.getAffineTransform, gTouchCalibrationClassInfo.clazz, "getAffineTransform", "()[F"); + // SparseArray + FIND_CLASS(gSparseArrayClassInfo.clazz, "android/util/SparseArray"); + gSparseArrayClassInfo.clazz = jclass(env->NewGlobalRef(gSparseArrayClassInfo.clazz)); + GET_METHOD_ID(gSparseArrayClassInfo.constructor, gSparseArrayClassInfo.clazz, "<init>", "()V"); + GET_METHOD_ID(gSparseArrayClassInfo.keyAt, gSparseArrayClassInfo.clazz, "keyAt", "(I)I"); + GET_METHOD_ID(gSparseArrayClassInfo.valueAt, gSparseArrayClassInfo.clazz, "valueAt", + "(I)Ljava/lang/Object;"); + GET_METHOD_ID(gSparseArrayClassInfo.size, gSparseArrayClassInfo.clazz, "size", "()I"); + return 0; } diff --git a/services/core/jni/com_android_server_vibrator_VibratorController.cpp b/services/core/jni/com_android_server_vibrator_VibratorController.cpp index afce5379febb..7ed37481f8cb 100644 --- a/services/core/jni/com_android_server_vibrator_VibratorController.cpp +++ b/services/core/jni/com_android_server_vibrator_VibratorController.cpp @@ -29,6 +29,8 @@ #include <vibratorservice/VibratorHalController.h> +#include "com_android_server_VibratorManagerService.h" + namespace V1_0 = android::hardware::vibrator::V1_0; namespace V1_1 = android::hardware::vibrator::V1_1; namespace V1_2 = android::hardware::vibrator::V1_2; @@ -70,13 +72,26 @@ static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) == static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) == static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK)); +static std::shared_ptr<vibrator::HalController> findVibrator(int32_t vibratorId) { + // TODO(b/167946816): remove this once VibratorService is removed. + if (vibratorId < 0) { + return std::move(std::make_unique<vibrator::HalController>()); + } + vibrator::ManagerHalWrapper* manager = android_server_VibratorManagerService_getManager(); + if (manager == nullptr) { + return nullptr; + } + auto result = manager->getVibrator(vibratorId); + return result.isOk() ? std::move(result.value()) : nullptr; +} + class VibratorControllerWrapper { public: VibratorControllerWrapper(JNIEnv* env, int32_t vibratorId, jobject callbackListener) - // TODO(b/167946816): use ManagerHalController to get vibrator by id - : mHal(std::make_unique<vibrator::HalController>()), + : mHal(std::move(findVibrator(vibratorId))), mVibratorId(vibratorId), mCallbackListener(env->NewGlobalRef(callbackListener)) { + LOG_ALWAYS_FATAL_IF(mHal == nullptr, "Unable to find reference to vibrator hal"); LOG_ALWAYS_FATAL_IF(mCallbackListener == nullptr, "Unable to create global reference to vibration callback handler"); } @@ -97,7 +112,7 @@ public: } private: - const std::unique_ptr<vibrator::HalController> mHal; + const std::shared_ptr<vibrator::HalController> mHal; const int32_t mVibratorId; const jobject mCallbackListener; }; diff --git a/services/core/jni/gnss/OWNERS b/services/core/jni/gnss/OWNERS new file mode 100644 index 000000000000..5ac6028411f0 --- /dev/null +++ b/services/core/jni/gnss/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/location/OWNERS diff --git a/services/core/xsd/platform-compat-schema/OWNERS b/services/core/xsd/platform-compat-schema/OWNERS new file mode 100644 index 000000000000..f8c3520e9fa8 --- /dev/null +++ b/services/core/xsd/platform-compat-schema/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/compat/OWNERS diff --git a/services/devicepolicy/OWNERS b/services/devicepolicy/OWNERS new file mode 100644 index 000000000000..e95633abe79a --- /dev/null +++ b/services/devicepolicy/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/admin/OWNERS diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java index ce61d50df1d9..6f1d451e7224 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java @@ -44,19 +44,19 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub { /** * To be called by {@link DevicePolicyManagerService#Lifecycle} when a new user starts. * - * @see {@link SystemService#onStartUser} + * @see {@link SystemService#onUserStarting} */ abstract void handleStartUser(int userId); /** * To be called by {@link DevicePolicyManagerService#Lifecycle} when a user is being unlocked. * - * @see {@link SystemService#onUnlockUser} + * @see {@link SystemService#onUserUnlocking} */ abstract void handleUnlockUser(int userId); /** * To be called by {@link DevicePolicyManagerService#Lifecycle} when a user is being stopped. * - * @see {@link SystemService#onStopUser} + * @see {@link SystemService#onUserStopping} */ abstract void handleStopUser(int userId); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index edcf9e8399a8..62cf3aa53e7c 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -2328,7 +2328,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { + admin.info.getTagForPolicy(reqPolicy)); } else { throw new SecurityException("No active admin owned by uid " - + callingUid + " for policy #" + reqPolicy); + + callingUid + " for policy #" + reqPolicy + (permission == null ? "" + : ", which doesn't have " + permission)); } } @@ -2388,6 +2389,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { * If not provided, iterate over all of the active admins in the DevicePolicyData for that user * and return the one with the uid specified as parameter, and has the policy specified. */ + @Nullable private ActiveAdmin getActiveAdminWithPolicyForUidLocked(ComponentName who, int reqPolicy, int uid) { ensureLocked(); @@ -5190,6 +5192,44 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } + @Override + public List<String> getKeyPairGrants(String callerPackage, String alias) { + final CallerIdentity caller = getCallerIdentity(callerPackage); + Preconditions.checkCallAuthorization(canManageCertificates(caller)); + + return mInjector.binderWithCleanCallingIdentity(() -> { + try (KeyChainConnection keyChainConnection = + KeyChain.bindAsUser(mContext, caller.getUserHandle())) { + final List<String> result = new ArrayList<>(); + final int[] granteeUids = keyChainConnection.getService().getGrants(alias); + final PackageManager pm = mInjector.getPackageManager(caller.getUserId()); + + // TODO: Return Set<Set<String>> when AIDL supports it: b/136048684 + // Public API returns a set of sets, where each internal set contains all package + // names corresponding to the same UID. For now a set of sets is marshalled as a + // null-separated list. + for (final int uid : granteeUids) { + final String[] packages = pm.getPackagesForUid(uid); + if (packages == null) { + Slog.wtf(LOG_TAG, "No packages found for uid " + uid); + continue; + } + if (!result.isEmpty()) { + result.add(null); + } + result.addAll(Arrays.asList(packages)); + } + return result; + } catch (RemoteException e) { + Log.e(LOG_TAG, "Querying keypair grants", e); + } catch (InterruptedException e) { + Log.w(LOG_TAG, "Interrupted while querying keypair grants", e); + Thread.currentThread().interrupt(); + } + return Collections.emptyList(); + }); + } + /** * Enforce one the following conditions are met: * (1) The device has a Device Owner, and one of the following holds: @@ -6096,10 +6136,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final ActiveAdmin admin; synchronized (getLockObject()) { - admin = getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_WIPE_DATA); + admin = getActiveAdminWithPolicyForUidLocked(/* who= */ null, + DeviceAdminInfo.USES_POLICY_WIPE_DATA, caller.getUid()); } - Preconditions.checkCallAuthorization(admin != null, - "No active admin for user %d", caller.getUserId()); + + Preconditions.checkCallAuthorization( + (admin != null) || hasCallingOrSelfPermission(permission.MASTER_CLEAR), + "No active admin for user %d and caller %d does not hold MASTER_CLEAR permission", + caller.getUserId(), caller.getUid()); if (TextUtils.isEmpty(wipeReasonForUser)) { if (calledByProfileOwnerOnOrgOwnedDevice && !calledOnParentInstance) { @@ -6110,7 +6154,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - int userId = admin.getUserHandle().getIdentifier(); + int userId = admin != null ? admin.getUserHandle().getIdentifier() + : caller.getUserId(); + Slog.i(LOG_TAG, String.format("wipeDataWithReason(%s): admin=%s, user=%d", + wipeReasonForUser, admin, userId)); if (calledByProfileOwnerOnOrgOwnedDevice) { // When wipeData is called on the parent instance, it implies wiping the entire device. if (calledOnParentInstance) { @@ -6133,20 +6180,35 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { }); } } - - DevicePolicyEventLogger + DevicePolicyEventLogger event = DevicePolicyEventLogger .createEvent(DevicePolicyEnums.WIPE_DATA_WITH_REASON) - .setAdmin(admin.info.getComponent()) .setInt(flags) .setStrings(calledOnParentInstance ? CALLED_FROM_PARENT : NOT_CALLED_FROM_PARENT) - .write(); + ; + final String adminName; + final ComponentName adminComp; + if (admin != null) { + adminComp = admin.info.getComponent(); + adminName = adminComp.flattenToShortString(); + event.setAdmin(adminComp); + } else { + adminComp = null; + adminName = mInjector.getPackageManager().getPackagesForUid(caller.getUid())[0]; + Slog.i(LOG_TAG, "Logging wipeData() event admin as " + adminName); + event.setAdmin(adminName); + if (mInjector.userManagerIsHeadlessSystemUserMode()) { + // On headless system user mode, the call is meant to factory reset the whole + // device, otherwise the caller could simply remove the current user. + userId = UserHandle.USER_SYSTEM; + } + } + event.write(); + String internalReason = String.format( "DevicePolicyManager.wipeDataWithReason() from %s, organization-owned? %s", - admin.info.getComponent().flattenToShortString(), - calledByProfileOwnerOnOrgOwnedDevice); + adminName, calledByProfileOwnerOnOrgOwnedDevice); - wipeDataNoLock( - admin.info.getComponent(), flags, internalReason, wipeReasonForUser, userId); + wipeDataNoLock(adminComp, flags, internalReason, wipeReasonForUser, userId); } private void wipeDataNoLock(ComponentName admin, int flags, String internalReason, @@ -12502,7 +12564,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(admin, "ComponentName is null"); final CallerIdentity caller = getCallerIdentity(admin); Preconditions.checkCallAuthorization(isDeviceOwner(caller)); - + checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_REBOOT); mInjector.binderWithCleanCallingIdentity(() -> { // Make sure there are no ongoing calls on the device. if (mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) { @@ -13416,14 +13478,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(admin); Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller)); - synchronized (getLockObject()) { - try { - IBackupManager ibm = mInjector.getIBackupManager(); - return ibm != null && ibm.isBackupServiceActive(caller.getUserId()); - } catch (RemoteException e) { - throw new IllegalStateException("Failed requesting backup service state.", e); + return mInjector.binderWithCleanCallingIdentity(() -> { + synchronized (getLockObject()) { + try { + IBackupManager ibm = mInjector.getIBackupManager(); + return ibm != null && ibm.isBackupServiceActive(caller.getUserId()); + } catch (RemoteException e) { + throw new IllegalStateException("Failed requesting backup service state.", e); + } } - } + }); } @Override diff --git a/services/incremental/OWNERS b/services/incremental/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/services/incremental/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 6525e1126478..92c64f822b78 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1252,6 +1252,10 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startService(DropBoxManagerService.class); t.traceEnd(); + t.traceBegin("StartVibratorManagerService"); + mSystemServiceManager.startService(VibratorManagerService.Lifecycle.class); + t.traceEnd(); + t.traceBegin("StartVibratorService"); vibrator = new VibratorService(context); ServiceManager.addService("vibrator", vibrator); diff --git a/services/people/OWNERS b/services/people/OWNERS new file mode 100644 index 000000000000..7ac9b7363f7f --- /dev/null +++ b/services/people/OWNERS @@ -0,0 +1,2 @@ +danningc@google.com +juliacr@google.com diff --git a/services/print/OWNERS b/services/print/OWNERS new file mode 100644 index 000000000000..2c7b881faf0f --- /dev/null +++ b/services/print/OWNERS @@ -0,0 +1 @@ +include /core/java/android/print/OWNERS diff --git a/services/restrictions/OWNERS b/services/restrictions/OWNERS new file mode 100644 index 000000000000..95e614c8a1bc --- /dev/null +++ b/services/restrictions/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/restrictions/OWNERS diff --git a/services/robotests/backup/OWNERS b/services/robotests/backup/OWNERS new file mode 100644 index 000000000000..d99779e3d9da --- /dev/null +++ b/services/robotests/backup/OWNERS @@ -0,0 +1 @@ +include /services/backup/OWNERS diff --git a/services/robotests/src/com/android/server/backup/OWNERS b/services/robotests/src/com/android/server/backup/OWNERS new file mode 100644 index 000000000000..d99779e3d9da --- /dev/null +++ b/services/robotests/src/com/android/server/backup/OWNERS @@ -0,0 +1 @@ +include /services/backup/OWNERS diff --git a/services/robotests/src/com/android/server/pm/OWNERS b/services/robotests/src/com/android/server/pm/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/services/robotests/src/com/android/server/pm/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/services/startop/OWNERS b/services/startop/OWNERS new file mode 100644 index 000000000000..bd3d829ed89f --- /dev/null +++ b/services/startop/OWNERS @@ -0,0 +1 @@ +include /startop/OWNERS diff --git a/services/tests/PackageManager/OWNERS b/services/tests/PackageManager/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/services/tests/PackageManager/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/services/tests/PackageManagerComponentOverrideTests/OWNERS b/services/tests/PackageManagerComponentOverrideTests/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/services/tests/PackageManagerComponentOverrideTests/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/services/tests/mockingservicestests/AndroidManifest.xml b/services/tests/mockingservicestests/AndroidManifest.xml index 182fe9ae9476..fbde1d2cf1cf 100644 --- a/services/tests/mockingservicestests/AndroidManifest.xml +++ b/services/tests/mockingservicestests/AndroidManifest.xml @@ -27,6 +27,9 @@ <uses-permission android:name="android.permission.MANAGE_APPOPS"/> <uses-permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS"/> + <!-- needed by MasterClearReceiverTest to display a system dialog --> + <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"/> + <application android:testOnly="true" android:debuggable="true"> <uses-library android:name="android.test.runner" /> diff --git a/services/tests/mockingservicestests/assets/AppOpsUpgradeTest/OWNERS b/services/tests/mockingservicestests/assets/AppOpsUpgradeTest/OWNERS new file mode 100644 index 000000000000..999ea0e62a0a --- /dev/null +++ b/services/tests/mockingservicestests/assets/AppOpsUpgradeTest/OWNERS @@ -0,0 +1 @@ +include /core/java/android/permission/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java b/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java new file mode 100644 index 000000000000..f01120e1ed4c --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; + +import static com.google.common.truth.Truth.assertWithMessage; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.never; + +import android.content.Context; +import android.content.ContextWrapper; +import android.content.Intent; +import android.os.Looper; +import android.os.RecoverySystem; +import android.os.storage.StorageManager; +import android.platform.test.annotations.Presubmit; +import android.util.Log; +import android.view.WindowManager; + +import androidx.test.InstrumentationRegistry; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoSession; +import org.mockito.quality.Strictness; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * Run it as {@code FrameworksMockingServicesTests:MasterClearReceiverTest}. + */ +@Presubmit +public final class MasterClearReceiverTest { + + private static final String TAG = MasterClearReceiverTest.class.getSimpleName(); + + private MockitoSession mSession; + + // Cannot @Mock context because MasterClearReceiver shows an AlertDialog, which relies + // on resources - we'd need to mock them as well. + private final Context mContext = new ContextWrapper( + InstrumentationRegistry.getInstrumentation().getTargetContext()) { + + @Override + public Object getSystemService(String name) { + Log.v(TAG, "getSystemService(): " + name); + return name.equals(Context.STORAGE_SERVICE) ? mSm : super.getSystemService(name); + } + }; + + private final MasterClearReceiver mReceiver = new MasterClearReceiver(); + + // Used to make sure that wipeAdoptableDisks() is called before rebootWipeUserData() + private boolean mWipeExternalDataCalled; + + // Uset to block test until rebootWipeUserData() is called, as it might be asynchronous called + // in a different thread + private final CountDownLatch mRebootWipeUserDataLatch = new CountDownLatch(1); + + @Mock + private StorageManager mSm; + + @Mock + private WindowManager mWm; + + @Before + public void startSession() { + mSession = mockitoSession() + .initMocks(this) + .mockStatic(RecoverySystem.class) + .strictness(Strictness.LENIENT) + .startMocking(); + } + + @After + public void finishSession() { + if (mSession == null) { + Log.w(TAG, "finishSession(): no session"); + return; + } + mSession.finishMocking(); + } + + @Test + public void testNoExtras() throws Exception { + expectNoWipeExternalData(); + expectRebootWipeUserData(); + + Intent intent = new Intent(Intent.ACTION_FACTORY_RESET); + mReceiver.onReceive(mContext, intent); + + verifyRebootWipeUserData(); + verifyNoWipeExternalData(); + } + + @Test + public void testWipeExternalDirectory() throws Exception { + expectWipeExternalData(); + expectRebootWipeUserData(); + + Intent intent = new Intent(Intent.ACTION_FACTORY_RESET); + intent.putExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, true); + mReceiver.onReceive(mContext, intent); + + verifyRebootWipeUserData(); + verifyWipeExternalData(); + } + + @Test + public void testAllExtras() throws Exception { + expectWipeExternalData(); + expectRebootWipeUserData(); + + Intent intent = new Intent(Intent.ACTION_FACTORY_RESET); + intent.putExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, true); + intent.putExtra("shutdown", true); + intent.putExtra(Intent.EXTRA_REASON, "Self destruct"); + intent.putExtra(Intent.EXTRA_FORCE_FACTORY_RESET, true); + intent.putExtra(Intent.EXTRA_WIPE_ESIMS, true); + mReceiver.onReceive(mContext, intent); + + verifyRebootWipeUserData(/* shutdown= */ true, /* reason= */ "Self destruct", + /* force= */ true, /* wipeEuicc= */ true); + verifyWipeExternalData(); + } + + + private void expectNoWipeExternalData() { + // This is a trick to simplify how the order of methods are called: as wipeAdoptableDisks() + // should be called before rebootWipeUserData(), expectRebootWipeUserData() throws an + // exception if it's not called, so this method "emulates" a call when it's not neeeded. + // + // A more robust solution would be using internal counters for expected and actual mocked + // calls, so the expectXXX() methods would increment expected counter and the Answer + // implementations would increment the actual counter and check if they match, but that + // would be an overkill (and make the test logic more complicated). + mWipeExternalDataCalled = true; + } + + private void expectRebootWipeUserData() { + doAnswer((inv) -> { + Log.i(TAG, inv.toString()); + if (!mWipeExternalDataCalled) { + String error = "rebootWipeUserData() called before wipeAdoptableDisks()"; + Log.e(TAG, error); + throw new IllegalStateException(error); + } + mRebootWipeUserDataLatch.countDown(); + return null; + }).when(() -> RecoverySystem + .rebootWipeUserData(any(), anyBoolean(), any(), anyBoolean(), anyBoolean())); + } + + private void expectWipeExternalData() { + Looper.prepare(); // needed by Dialog + + doAnswer((inv) -> { + Log.i(TAG, inv.toString()); + mWipeExternalDataCalled = true; + return null; + }).when(mSm).wipeAdoptableDisks(); + } + + private void verifyRebootWipeUserData() throws Exception { + verifyRebootWipeUserData(/* shutdown= */ false, /* reason= */ null, /* force= */ false, + /* wipeEuicc= */ false); + + } + + private void verifyRebootWipeUserData(boolean shutdown, String reason, boolean force, + boolean wipeEuicc) throws Exception { + boolean called = mRebootWipeUserDataLatch.await(5, TimeUnit.SECONDS); + assertWithMessage("rebootWipeUserData not called in 5s").that(called).isTrue(); + + verify(()-> RecoverySystem.rebootWipeUserData(same(mContext), eq(shutdown), eq(reason), + eq(force), eq(wipeEuicc))); + } + + private void verifyWipeExternalData() { + verify(mSm).wipeAdoptableDisks(); + } + + private void verifyNoWipeExternalData() { + verify(mSm, never()).wipeAdoptableDisks(); + } +} diff --git a/services/tests/mockingservicestests/src/com/android/server/OWNERS b/services/tests/mockingservicestests/src/com/android/server/OWNERS new file mode 100644 index 000000000000..e779e21bb987 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/OWNERS @@ -0,0 +1 @@ +per-file *Alarm* = file:/apex/jobscheduler/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/OWNERS b/services/tests/mockingservicestests/src/com/android/server/alarm/OWNERS new file mode 100644 index 000000000000..6f207fb1a00e --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/alarm/OWNERS @@ -0,0 +1 @@ +include /apex/jobscheduler/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/am/OWNERS b/services/tests/mockingservicestests/src/com/android/server/am/OWNERS new file mode 100644 index 000000000000..72c0a9e6e90c --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/am/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/am/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/OWNERS b/services/tests/mockingservicestests/src/com/android/server/appop/OWNERS new file mode 100644 index 000000000000..999ea0e62a0a --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/appop/OWNERS @@ -0,0 +1 @@ +include /core/java/android/permission/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/blob/OWNERS b/services/tests/mockingservicestests/src/com/android/server/blob/OWNERS new file mode 100644 index 000000000000..65bb6b8a5423 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/blob/OWNERS @@ -0,0 +1 @@ +include /apex/blobstore/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/display/OWNERS b/services/tests/mockingservicestests/src/com/android/server/display/OWNERS new file mode 100644 index 000000000000..6ce1ee4d3de2 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/display/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/display/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/job/OWNERS b/services/tests/mockingservicestests/src/com/android/server/job/OWNERS new file mode 100644 index 000000000000..6f207fb1a00e --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/job/OWNERS @@ -0,0 +1 @@ +include /apex/jobscheduler/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java index e331507ef597..63b36fc68fcd 100644 --- a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java @@ -60,6 +60,7 @@ import static org.testng.Assert.assertThrows; import android.content.Context; import android.location.ILocationCallback; import android.location.ILocationListener; +import android.location.LastLocationRequest; import android.location.Location; import android.location.LocationManagerInternal; import android.location.LocationManagerInternal.ProviderEnabledListener; @@ -260,55 +261,77 @@ public class LocationProviderManagerTest { @Test public void testGetLastLocation_Fine() { - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull(); + assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY, + PERMISSION_FINE)).isNull(); Location loc = createLocation(NAME, mRandom); mProvider.setProviderLocation(loc); - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc); + assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY, + PERMISSION_FINE)).isEqualTo(loc); } @Test public void testGetLastLocation_Coarse() { - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull(); + assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY, + PERMISSION_FINE)).isNull(); Location loc = createLocation(NAME, mRandom); mProvider.setProviderLocation(loc); - Location coarse = mManager.getLastLocation(IDENTITY, PERMISSION_COARSE, false); + Location coarse = mManager.getLastLocation(new LastLocationRequest.Builder().build(), + IDENTITY, PERMISSION_COARSE); assertThat(coarse).isNotEqualTo(loc); assertThat(coarse).isNearby(loc, 5000); } @Test public void testGetLastLocation_Bypass() { - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull(); - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isNull(); + assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY, + PERMISSION_FINE)).isNull(); + assertThat(mManager.getLastLocation( + new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(), + IDENTITY, PERMISSION_FINE)).isNull(); Location loc = createLocation(NAME, mRandom); mProvider.setProviderLocation(loc); - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc); - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isEqualTo( + assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY, + PERMISSION_FINE)).isEqualTo(loc); + assertThat(mManager.getLastLocation( + new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(), + IDENTITY, PERMISSION_FINE)).isEqualTo( loc); mProvider.setProviderAllowed(false); - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull(); - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isEqualTo( + assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY, + PERMISSION_FINE)).isNull(); + assertThat(mManager.getLastLocation( + new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(), + IDENTITY, PERMISSION_FINE)).isEqualTo( loc); loc = createLocation(NAME, mRandom); mProvider.setProviderLocation(loc); - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull(); - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isEqualTo( + assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY, + PERMISSION_FINE)).isNull(); + assertThat(mManager.getLastLocation( + new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(), + IDENTITY, PERMISSION_FINE)).isEqualTo( loc); mProvider.setProviderAllowed(true); - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull(); - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isEqualTo( + assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY, + PERMISSION_FINE)).isNull(); + assertThat(mManager.getLastLocation( + new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(), + IDENTITY, PERMISSION_FINE)).isEqualTo( loc); loc = createLocation(NAME, mRandom); mProvider.setProviderLocation(loc); - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc); - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isEqualTo( + assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY, + PERMISSION_FINE)).isEqualTo(loc); + assertThat(mManager.getLastLocation( + new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(), + IDENTITY, PERMISSION_FINE)).isEqualTo( loc); } @@ -320,10 +343,12 @@ public class LocationProviderManagerTest { Location loc = createLocation(NAME, mRandom); mockProvider.setProviderLocation(loc); - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc); + assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY, + PERMISSION_FINE)).isEqualTo(loc); mManager.setMockProvider(null); - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull(); + assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY, + PERMISSION_FINE)).isNull(); } @Test @@ -331,12 +356,14 @@ public class LocationProviderManagerTest { Location loc1 = createLocation(NAME, mRandom); mManager.injectLastLocation(loc1, CURRENT_USER); - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc1); + assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY, + PERMISSION_FINE)).isEqualTo(loc1); Location loc2 = createLocation(NAME, mRandom); mManager.injectLastLocation(loc2, CURRENT_USER); - assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc1); + assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY, + PERMISSION_FINE)).isEqualTo(loc1); } @Test @@ -355,7 +382,8 @@ public class LocationProviderManagerTest { Location loc = createLocation(NAME, mRandom); mProvider.setProviderLocation(loc); - assertThat(mPassive.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc); + assertThat(mPassive.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY, + PERMISSION_FINE)).isEqualTo(loc); } @Test diff --git a/services/tests/mockingservicestests/src/com/android/server/power/OWNERS b/services/tests/mockingservicestests/src/com/android/server/power/OWNERS new file mode 100644 index 000000000000..d68066bb8c40 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/power/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/power/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/usage/OWNERS b/services/tests/mockingservicestests/src/com/android/server/usage/OWNERS new file mode 100644 index 000000000000..d3227de87684 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/usage/OWNERS @@ -0,0 +1 @@ +include /services/usage/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/OWNERS b/services/tests/mockingservicestests/src/com/android/server/wallpaper/OWNERS new file mode 100644 index 000000000000..8ff0f74202f8 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/wallpaper/OWNERS diff --git a/services/tests/servicestests/apks/OWNERS b/services/tests/servicestests/apks/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/services/tests/servicestests/apks/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/services/tests/servicestests/assets/NetworkPolicy/OWNERS b/services/tests/servicestests/assets/NetworkPolicy/OWNERS new file mode 100644 index 000000000000..aa87958f1d53 --- /dev/null +++ b/services/tests/servicestests/assets/NetworkPolicy/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/net/OWNERS diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/OWNERS b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/OWNERS new file mode 100644 index 000000000000..aa87958f1d53 --- /dev/null +++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/net/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java index a02c53336da0..6814c050a845 100644 --- a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java @@ -163,16 +163,26 @@ public class GestureLauncherServiceTest { } @Test - public void testIsEmergencyGestureEnabled_settingDisabled() { + public void testIsEmergencyGestureSettingEnabled_settingDisabled() { + withEmergencyGestureEnabledConfigValue(true); withEmergencyGestureEnabledSettingValue(false); - assertFalse(mGestureLauncherService.isEmergencyGestureEnabled( + assertFalse(mGestureLauncherService.isEmergencyGestureSettingEnabled( mContext, FAKE_USER_ID)); } @Test - public void testIsEmergencyGestureEnabled_settingEnabled() { + public void testIsEmergencyGestureSettingEnabled_settingEnabled() { + withEmergencyGestureEnabledConfigValue(true); withEmergencyGestureEnabledSettingValue(true); - assertTrue(mGestureLauncherService.isEmergencyGestureEnabled( + assertTrue(mGestureLauncherService.isEmergencyGestureSettingEnabled( + mContext, FAKE_USER_ID)); + } + + @Test + public void testIsEmergencyGestureSettingEnabled_supportDisabled() { + withEmergencyGestureEnabledConfigValue(false); + withEmergencyGestureEnabledSettingValue(true); + assertFalse(mGestureLauncherService.isEmergencyGestureSettingEnabled( mContext, FAKE_USER_ID)); } @@ -438,6 +448,7 @@ public class GestureLauncherServiceTest { testInterceptPowerKeyDown_fiveInboundPresses_cameraAndEmergencyEnabled_bothLaunch() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); + withEmergencyGestureEnabledConfigValue(true); withEmergencyGestureEnabledSettingValue(true); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); mGestureLauncherService.updateEmergencyGestureEnabled(); @@ -527,6 +538,7 @@ public class GestureLauncherServiceTest { @Test public void testInterceptPowerKeyDown_fiveInboundPresses_emergencyGestureEnabled_launchesFlow() { + withEmergencyGestureEnabledConfigValue(true); withEmergencyGestureEnabledSettingValue(true); mGestureLauncherService.updateEmergencyGestureEnabled(); withUserSetupCompleteValue(true); @@ -580,6 +592,7 @@ public class GestureLauncherServiceTest { @Test public void testInterceptPowerKeyDown_tenInboundPresses_emergencyGestureEnabled_keyIntercepted() { + withEmergencyGestureEnabledConfigValue(true); withEmergencyGestureEnabledSettingValue(true); mGestureLauncherService.updateEmergencyGestureEnabled(); withUserSetupCompleteValue(true); @@ -1146,6 +1159,12 @@ public class GestureLauncherServiceTest { .thenReturn(enableConfigValue); } + private void withEmergencyGestureEnabledConfigValue(boolean enableConfigValue) { + when(mResources.getBoolean( + com.android.internal.R.bool.config_emergencyGestureEnabled)) + .thenReturn(enableConfigValue); + } + private void withCameraDoubleTapPowerDisableSettingValue(int disableSettingValue) { Settings.Secure.putIntForUser( mContentResolver, diff --git a/services/tests/servicestests/src/com/android/server/OWNERS b/services/tests/servicestests/src/com/android/server/OWNERS new file mode 100644 index 000000000000..2463fc617f0b --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/OWNERS @@ -0,0 +1,7 @@ +per-file *Alarm* = file:/apex/jobscheduler/OWNERS +per-file *AppOps* = file:/core/java/android/permission/OWNERS +per-file *Bluetooth* = file:/core/java/android/bluetooth/OWNERS +per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS +per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS +per-file *Vibrator* = file:/services/core/java/com/android/server/vibrator/OWNERS +per-file GestureLauncherServiceTest.java = file:platform/packages/apps/EmergencyInfo:/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/VibratorManagerServiceTest.java index 044bdbadb946..726536db859e 100644 --- a/services/tests/servicestests/src/com/android/server/VibratorManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/VibratorManagerServiceTest.java @@ -19,17 +19,38 @@ package com.android.server; import static com.android.server.testutils.TestUtils.assertExpectException; import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.hardware.vibrator.IVibrator; import android.os.CombinedVibrationEffect; +import android.os.Handler; +import android.os.Looper; +import android.os.PowerManager; +import android.os.PowerManagerInternal; +import android.os.PowerSaveState; import android.os.Process; import android.os.VibrationAttributes; import android.os.VibrationEffect; +import android.os.Vibrator; +import android.os.VibratorInfo; +import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; import androidx.test.InstrumentationRegistry; +import com.android.server.vibrator.VibratorController; + +import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -37,6 +58,9 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import java.util.HashMap; +import java.util.Map; + /** * Tests for {@link VibratorManagerService}. * @@ -51,24 +75,54 @@ public class VibratorManagerServiceTest { private static final VibrationAttributes ALARM_ATTRS = new VibrationAttributes.Builder().setUsage(VibrationAttributes.USAGE_ALARM).build(); - @Rule - public MockitoRule rule = MockitoJUnit.rule(); + @Rule public MockitoRule rule = MockitoJUnit.rule(); + + @Mock private VibratorManagerService.NativeWrapper mNativeWrapperMock; + @Mock private PowerManagerInternal mPowerManagerInternalMock; + @Mock private PowerSaveState mPowerSaveStateMock; + + private final Map<Integer, VibratorController.NativeWrapper> mNativeWrappers = new HashMap<>(); - @Mock - private VibratorManagerService.NativeWrapper mNativeWrapperMock; + private TestLooper mTestLooper; @Before public void setUp() throws Exception { + mTestLooper = new TestLooper(); + + when(mPowerManagerInternalMock.getLowPowerState(PowerManager.ServiceType.VIBRATION)) + .thenReturn(mPowerSaveStateMock); + + addLocalServiceMock(PowerManagerInternal.class, mPowerManagerInternalMock); + } + + @After + public void tearDown() throws Exception { + LocalServices.removeServiceForTest(PowerManagerInternal.class); } private VibratorManagerService createService() { - return new VibratorManagerService(InstrumentationRegistry.getContext(), + VibratorManagerService service = new VibratorManagerService( + InstrumentationRegistry.getContext(), new VibratorManagerService.Injector() { @Override VibratorManagerService.NativeWrapper getNativeWrapper() { return mNativeWrapperMock; } + + @Override + Handler createHandler(Looper looper) { + return new Handler(mTestLooper.getLooper()); + } + + @Override + VibratorController createVibratorController(int vibratorId, + VibratorController.OnVibrationCompleteListener listener) { + return new VibratorController( + vibratorId, listener, mNativeWrappers.get(vibratorId)); + } }); + service.systemReady(); + return service; } @Test @@ -85,8 +139,156 @@ public class VibratorManagerServiceTest { @Test public void getVibratorIds_withNonEmptyResultFromNative_returnsSameArray() { - when(mNativeWrapperMock.getVibratorIds()).thenReturn(new int[]{1, 2}); - assertArrayEquals(new int[]{1, 2}, createService().getVibratorIds()); + mNativeWrappers.put(1, mockVibrator(/* capabilities= */ 0)); + mNativeWrappers.put(2, mockVibrator(/* capabilities= */ 0)); + when(mNativeWrapperMock.getVibratorIds()).thenReturn(new int[]{2, 1}); + assertArrayEquals(new int[]{2, 1}, createService().getVibratorIds()); + } + + @Test + public void getVibratorInfo_withMissingVibratorId_returnsNull() { + mockVibrators(mockVibrator(/* capabilities= */ 0)); + assertNull(createService().getVibratorInfo(2)); + } + + @Test + public void getVibratorInfo_withExistingVibratorId_returnsHalInfoForVibrator() { + VibratorController.NativeWrapper vibratorMock = mockVibrator( + IVibrator.CAP_COMPOSE_EFFECTS | IVibrator.CAP_AMPLITUDE_CONTROL); + when(vibratorMock.getSupportedEffects()).thenReturn( + new int[]{VibrationEffect.EFFECT_CLICK}); + when(vibratorMock.getSupportedPrimitives()).thenReturn( + new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}); + mNativeWrappers.put(1, vibratorMock); + when(mNativeWrapperMock.getVibratorIds()).thenReturn(new int[]{1}); + VibratorInfo info = createService().getVibratorInfo(1); + + assertNotNull(info); + assertEquals(1, info.getId()); + assertTrue(info.hasAmplitudeControl()); + assertTrue(info.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)); + assertFalse(info.hasCapability(IVibrator.CAP_ON_CALLBACK)); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_YES, + info.isEffectSupported(VibrationEffect.EFFECT_CLICK)); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_NO, + info.isEffectSupported(VibrationEffect.EFFECT_TICK)); + assertTrue(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK)); + assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_TICK)); + } + + @Test + public void setAlwaysOnEffect_withMono_enablesAlwaysOnEffectToAllVibratorsWithCapability() { + VibratorController.NativeWrapper[] vibratorMocks = new VibratorController.NativeWrapper[]{ + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL), + mockVibrator(/* capabilities= */ 0), + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL), + }; + mockVibrators(vibratorMocks); + + CombinedVibrationEffect effect = CombinedVibrationEffect.createSynced( + VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)); + assertTrue(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS)); + + // Only vibrators 0 and 2 have always-on capabilities. + verify(vibratorMocks[0]).alwaysOnEnable( + eq(1L), eq((long) VibrationEffect.EFFECT_CLICK), + eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG)); + verify(vibratorMocks[1], never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); + verify(vibratorMocks[2]).alwaysOnEnable( + eq(1L), eq((long) VibrationEffect.EFFECT_CLICK), + eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG)); + } + + @Test + public void setAlwaysOnEffect_withStereo_enablesAlwaysOnEffectToAllVibratorsWithCapability() { + VibratorController.NativeWrapper[] vibratorMocks = new VibratorController.NativeWrapper[] { + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL), + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL), + mockVibrator(0), + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL), + }; + mockVibrators(vibratorMocks); + + CombinedVibrationEffect effect = CombinedVibrationEffect.startSynced() + .addVibrator(0, VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)) + .addVibrator(1, VibrationEffect.createPredefined(VibrationEffect.EFFECT_TICK)) + .addVibrator(2, VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)) + .combine(); + assertTrue(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS)); + + // Enables click on vibrator 0 and tick on vibrator 1 only. + verify(vibratorMocks[0]).alwaysOnEnable( + eq(1L), eq((long) VibrationEffect.EFFECT_CLICK), + eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG)); + verify(vibratorMocks[1]).alwaysOnEnable( + eq(1L), eq((long) VibrationEffect.EFFECT_TICK), + eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG)); + verify(vibratorMocks[2], never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); + verify(vibratorMocks[3], never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); + } + + @Test + public void setAlwaysOnEffect_withNullEffect_disablesAlwaysOnEffects() { + VibratorController.NativeWrapper[] vibratorMocks = new VibratorController.NativeWrapper[] { + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL), + mockVibrator(0), + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL), + }; + mockVibrators(vibratorMocks); + + assertTrue(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, null, ALARM_ATTRS)); + + // Disables only 0 and 2 that have capability. + verify(vibratorMocks[0]).alwaysOnDisable(eq(1L)); + verify(vibratorMocks[1], never()).alwaysOnDisable(anyLong()); + verify(vibratorMocks[2]).alwaysOnDisable(eq(1L)); + } + + @Test + public void setAlwaysOnEffect_withNonPrebakedEffect_ignoresEffect() { + VibratorController.NativeWrapper vibratorMock = + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL); + mockVibrators(vibratorMock); + + CombinedVibrationEffect effect = CombinedVibrationEffect.createSynced( + VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE)); + assertFalse(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS)); + + verify(vibratorMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); + verify(vibratorMock, never()).alwaysOnDisable(anyLong()); + } + + @Test + public void setAlwaysOnEffect_withNonSyncedEffect_ignoresEffect() { + VibratorController.NativeWrapper vibratorMock = + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL); + mockVibrators(vibratorMock); + + CombinedVibrationEffect effect = CombinedVibrationEffect.startSequential() + .addNext(0, VibrationEffect.get(VibrationEffect.EFFECT_CLICK)) + .combine(); + assertFalse(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS)); + + verify(vibratorMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); + verify(vibratorMock, never()).alwaysOnDisable(anyLong()); + } + + @Test + public void setAlwaysOnEffect_withNoVibratorWithCapability_ignoresEffect() { + VibratorController.NativeWrapper vibratorMock = mockVibrator(0); + mockVibrators(vibratorMock); + VibratorManagerService service = createService(); + + CombinedVibrationEffect mono = CombinedVibrationEffect.createSynced( + VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)); + CombinedVibrationEffect stereo = CombinedVibrationEffect.startSynced() + .addVibrator(0, VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)) + .combine(); + assertFalse(service.setAlwaysOnEffect(UID, PACKAGE_NAME, 1, mono, ALARM_ATTRS)); + assertFalse(service.setAlwaysOnEffect(UID, PACKAGE_NAME, 2, stereo, ALARM_ATTRS)); + + verify(vibratorMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); + verify(vibratorMock, never()).alwaysOnDisable(anyLong()); } @Test @@ -107,4 +309,24 @@ public class VibratorManagerServiceTest { assertExpectException(UnsupportedOperationException.class, "Not implemented", () -> service.cancelVibrate(service)); } + + private VibratorController.NativeWrapper mockVibrator(int capabilities) { + VibratorController.NativeWrapper wrapper = mock(VibratorController.NativeWrapper.class); + when(wrapper.getCapabilities()).thenReturn((long) capabilities); + return wrapper; + } + + private void mockVibrators(VibratorController.NativeWrapper... wrappers) { + int[] ids = new int[wrappers.length]; + for (int i = 0; i < wrappers.length; i++) { + ids[i] = i; + mNativeWrappers.put(i, wrappers[i]); + } + when(mNativeWrapperMock.getVibratorIds()).thenReturn(ids); + } + + private static <T> void addLocalServiceMock(Class<T> clazz, T mock) { + LocalServices.removeServiceForTest(clazz); + LocalServices.addService(clazz, mock); + } } diff --git a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java index 64f31358ccb3..68adacd8478f 100644 --- a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java @@ -16,7 +16,6 @@ package com.android.server; -import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -52,7 +51,6 @@ import android.os.Handler; import android.os.IBinder; import android.os.IVibratorStateListener; import android.os.Looper; -import android.os.PowerManager; import android.os.PowerManagerInternal; import android.os.PowerSaveState; import android.os.Process; @@ -62,6 +60,7 @@ import android.os.UserHandle; import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.Vibrator; +import android.os.VibratorInfo; import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; import android.provider.Settings; @@ -101,6 +100,9 @@ public class VibratorServiceTest { private static final int UID = Process.ROOT_UID; private static final String PACKAGE_NAME = "package"; + private static final PowerSaveState NORMAL_POWER_STATE = new PowerSaveState.Builder().build(); + private static final PowerSaveState LOW_POWER_STATE = new PowerSaveState.Builder() + .setBatterySaverEnabled(true).build(); private static final VibrationAttributes ALARM_ATTRS = new VibrationAttributes.Builder().setUsage(VibrationAttributes.USAGE_ALARM).build(); private static final VibrationAttributes HAPTIC_FEEDBACK_ATTRS = @@ -118,7 +120,6 @@ public class VibratorServiceTest { @Mock private PackageManagerInternal mPackageManagerInternalMock; @Mock private PowerManagerInternal mPowerManagerInternalMock; - @Mock private PowerSaveState mPowerSaveStateMock; // TODO(b/131311651): replace with a FakeVibrator instead. @Mock private Vibrator mVibratorMock; @Mock private AppOpsManager mAppOpsManagerMock; @@ -129,6 +130,7 @@ public class VibratorServiceTest { private TestLooper mTestLooper; private ContextWrapper mContextSpy; + private PowerManagerInternal.LowPowerModeListener mRegisteredPowerModeListener; @Before public void setUp() throws Exception { @@ -150,8 +152,10 @@ public class VibratorServiceTest { when(mVibratorStateListenerMock.asBinder()).thenReturn(mVibratorStateListenerBinderMock); when(mPackageManagerInternalMock.getSystemUiServiceComponent()) .thenReturn(new ComponentName("", "")); - when(mPowerManagerInternalMock.getLowPowerState(PowerManager.ServiceType.VIBRATION)) - .thenReturn(mPowerSaveStateMock); + doAnswer(invocation -> { + mRegisteredPowerModeListener = invocation.getArgument(0); + return null; + }).when(mPowerManagerInternalMock).registerLowPowerModeObserver(any()); when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[0]); setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1); @@ -199,7 +203,7 @@ public class VibratorServiceTest { public void createService_initializesNativeService() { createService(); verify(mNativeWrapperMock).init(eq(0), notNull()); - verify(mNativeWrapperMock).off(); + verify(mNativeWrapperMock, times(2)).off(); // Called from constructor and onSystemReady } @Test @@ -235,93 +239,21 @@ public class VibratorServiceTest { } @Test - public void areEffectsSupported_withNullResultFromNative_returnsSupportUnknown() { - when(mNativeWrapperMock.getSupportedEffects()).thenReturn(null); - assertArrayEquals(new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN}, - createService().areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK})); - } - - @Test - public void areEffectsSupported_withSomeEffectsSupported_returnsSupportYesAndNoForEffects() { - int[] effects = new int[]{VibrationEffect.EFFECT_CLICK, VibrationEffect.EFFECT_TICK}; - + public void getVibratorInfo_returnsSameInfoFromNative() { + mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS | IVibrator.CAP_AMPLITUDE_CONTROL); when(mNativeWrapperMock.getSupportedEffects()) .thenReturn(new int[]{VibrationEffect.EFFECT_CLICK}); - assertArrayEquals( - new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_YES, - Vibrator.VIBRATION_EFFECT_SUPPORT_NO}, - createService().areEffectsSupported(effects)); - } - - @Test - public void arePrimitivesSupported_withoutComposeCapability_returnsAlwaysFalse() { - assertArrayEquals(new boolean[]{false, false}, - createService().arePrimitivesSupported(new int[]{ - VibrationEffect.Composition.PRIMITIVE_CLICK, - VibrationEffect.Composition.PRIMITIVE_TICK - })); - } - - @Test - public void arePrimitivesSupported_withNullResultFromNative_returnsAlwaysFalse() { - mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); - when(mNativeWrapperMock.getSupportedPrimitives()).thenReturn(null); - - assertArrayEquals(new boolean[]{false, false}, - createService().arePrimitivesSupported(new int[]{ - VibrationEffect.Composition.PRIMITIVE_CLICK, - VibrationEffect.Composition.PRIMITIVE_QUICK_RISE - })); - } - - @Test - public void arePrimitivesSupported_withSomeSupportedPrimitives_returnsBasedOnNativeResult() { - mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); when(mNativeWrapperMock.getSupportedPrimitives()) .thenReturn(new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}); - assertArrayEquals(new boolean[]{true, false}, - createService().arePrimitivesSupported(new int[]{ - VibrationEffect.Composition.PRIMITIVE_CLICK, - VibrationEffect.Composition.PRIMITIVE_QUICK_RISE - })); - } - - @Test - public void setAlwaysOnEffect_withCapabilityAndValidEffect_enablesAlwaysOnEffect() { - mockVibratorCapabilities(IVibrator.CAP_ALWAYS_ON_CONTROL); - - assertTrue(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, - VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK), ALARM_ATTRS)); - verify(mNativeWrapperMock).alwaysOnEnable( - eq(1L), eq((long) VibrationEffect.EFFECT_CLICK), - eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG)); - } - - @Test - public void setAlwaysOnEffect_withNonPrebakedEffect_ignoresEffect() { - mockVibratorCapabilities(IVibrator.CAP_ALWAYS_ON_CONTROL); - - assertFalse(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, - VibrationEffect.createOneShot(100, 255), ALARM_ATTRS)); - verify(mNativeWrapperMock, never()).alwaysOnDisable(anyLong()); - verify(mNativeWrapperMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); - } - - @Test - public void setAlwaysOnEffect_withNullEffect_disablesAlwaysOnEffect() { - mockVibratorCapabilities(IVibrator.CAP_ALWAYS_ON_CONTROL); - - assertTrue(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, null, ALARM_ATTRS)); - verify(mNativeWrapperMock).alwaysOnDisable(eq(1L)); - } - - @Test - public void setAlwaysOnEffect_withoutCapability_ignoresEffect() { - assertFalse(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, - VibrationEffect.get(VibrationEffect.EFFECT_CLICK), ALARM_ATTRS)); - verify(mNativeWrapperMock, never()).alwaysOnDisable(anyLong()); - verify(mNativeWrapperMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); + VibratorInfo info = createService().getVibratorInfo(); + assertTrue(info.hasAmplitudeControl()); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_YES, + info.isEffectSupported(VibrationEffect.EFFECT_CLICK)); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_NO, + info.isEffectSupported(VibrationEffect.EFFECT_TICK)); + assertTrue(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK)); + assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_TICK)); } @Test @@ -346,6 +278,24 @@ public class VibratorServiceTest { } @Test + public void vibrate_withPowerModeChange_usesLowPowerModeState() { + VibratorService service = createService(); + mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE); + vibrate(service, VibrationEffect.createOneShot(1, 1), HAPTIC_FEEDBACK_ATTRS); + vibrate(service, VibrationEffect.createOneShot(2, 2), RINGTONE_ATTRS); + + mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE); + vibrate(service, VibrationEffect.createOneShot(3, 3), /* attributes= */ null); + vibrate(service, VibrationEffect.createOneShot(4, 4), NOTIFICATION_ATTRS); + + InOrder inOrderVerifier = inOrder(mNativeWrapperMock); + inOrderVerifier.verify(mNativeWrapperMock, never()).on(eq(1L), anyLong()); + inOrderVerifier.verify(mNativeWrapperMock).on(eq(2L), anyLong()); + inOrderVerifier.verify(mNativeWrapperMock).on(eq(3L), anyLong()); + inOrderVerifier.verify(mNativeWrapperMock).on(eq(4L), anyLong()); + } + + @Test public void vibrate_withAudioAttributes_usesOriginalAudioUsageInAppOpsManager() { VibratorService service = createService(); diff --git a/services/tests/servicestests/src/com/android/server/accessibility/OWNERS b/services/tests/servicestests/src/com/android/server/accessibility/OWNERS new file mode 100644 index 000000000000..b74281edbf52 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/accessibility/OWNERS @@ -0,0 +1 @@ +include /core/java/android/view/accessibility/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/accounts/OWNERS b/services/tests/servicestests/src/com/android/server/accounts/OWNERS new file mode 100644 index 000000000000..df1b4f432cd6 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/accounts/OWNERS @@ -0,0 +1 @@ +include /core/java/android/accounts/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/adb/OWNERS b/services/tests/servicestests/src/com/android/server/adb/OWNERS new file mode 100644 index 000000000000..b97f7956d115 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/adb/OWNERS @@ -0,0 +1 @@ +include platform/packages/modules/adb:/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/am/OWNERS b/services/tests/servicestests/src/com/android/server/am/OWNERS new file mode 100644 index 000000000000..72c0a9e6e90c --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/am/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/am/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/appop/OWNERS b/services/tests/servicestests/src/com/android/server/appop/OWNERS new file mode 100644 index 000000000000..999ea0e62a0a --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/appop/OWNERS @@ -0,0 +1 @@ +include /core/java/android/permission/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/appsearch/OWNERS b/services/tests/servicestests/src/com/android/server/appsearch/OWNERS new file mode 100644 index 000000000000..ebe9e4ec087f --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/appsearch/OWNERS @@ -0,0 +1 @@ +include /apex/appsearch/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/attention/OWNERS b/services/tests/servicestests/src/com/android/server/attention/OWNERS new file mode 100644 index 000000000000..51fc9bd09e4f --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/attention/OWNERS @@ -0,0 +1 @@ +include /core/java/android/attention/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/backup/OWNERS b/services/tests/servicestests/src/com/android/server/backup/OWNERS new file mode 100644 index 000000000000..d99779e3d9da --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/backup/OWNERS @@ -0,0 +1 @@ +include /services/backup/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/compat/OWNERS b/services/tests/servicestests/src/com/android/server/compat/OWNERS new file mode 100644 index 000000000000..f8c3520e9fa8 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/compat/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/compat/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OWNERS b/services/tests/servicestests/src/com/android/server/devicepolicy/OWNERS new file mode 100644 index 000000000000..e95633abe79a --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/admin/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/devicestate/OWNERS b/services/tests/servicestests/src/com/android/server/devicestate/OWNERS new file mode 100644 index 000000000000..d9b0e2e5ffa5 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/devicestate/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/devicestate/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/display/OWNERS b/services/tests/servicestests/src/com/android/server/display/OWNERS new file mode 100644 index 000000000000..6ce1ee4d3de2 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/display/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/display/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java index 2f49fb79c3dc..2cb1113e7325 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java @@ -25,6 +25,8 @@ import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED; import static com.android.server.hdmi.Constants.MESSAGE_DEVICE_VENDOR_ID; import static com.android.server.hdmi.Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS; +import static com.google.common.truth.Truth.assertThat; + import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; @@ -264,4 +266,14 @@ public class HdmiCecLocalDeviceTest { assertFalse(result); } + + @Test + public void handleCecVersion_isHandled() { + boolean result = mHdmiLocalDevice.onMessage( + HdmiCecMessageBuilder.buildCecVersion(ADDR_PLAYBACK_1, mHdmiLocalDevice.mAddress, + HdmiControlManager.HDMI_CEC_VERSION_1_4_b)); + + assertThat(result).isTrue(); + } + } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java index 080b52bbbc6a..e37001805398 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java @@ -36,6 +36,7 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -313,6 +314,7 @@ public class HdmiCecNetworkTest { int powerStatus = HdmiControlManager.POWER_STATUS_ON; String osdName = "Test Device"; int vendorId = 1234; + int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0; mHdmiCecNetwork.handleCecMessage( HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(logicalAddress, @@ -325,6 +327,8 @@ public class HdmiCecNetworkTest { Constants.ADDR_BROADCAST, osdName)); mHdmiCecNetwork.handleCecMessage( HdmiCecMessageBuilder.buildDeviceVendorIdCommand(logicalAddress, vendorId)); + mHdmiCecNetwork.handleCecMessage(HdmiCecMessageBuilder.buildCecVersion(logicalAddress, + Constants.ADDR_BROADCAST, cecVersion)); assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1); @@ -335,6 +339,7 @@ public class HdmiCecNetworkTest { assertThat(cecDeviceInfo.getDisplayName()).isEqualTo(osdName); assertThat(cecDeviceInfo.getVendorId()).isEqualTo(vendorId); assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(powerStatus); + assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion); } @Test @@ -374,16 +379,18 @@ public class HdmiCecNetworkTest { mHdmiCecNetwork.handleCecMessage( HdmiCecMessageBuilder.buildReportPowerStatus(logicalAddress, - Constants.ADDR_BROADCAST, powerStatus)); + Constants.ADDR_TV, powerStatus)); mHdmiCecNetwork.handleCecMessage( HdmiCecMessageBuilder.buildReportPowerStatus(logicalAddress, - Constants.ADDR_BROADCAST, updatedPowerStatus)); + Constants.ADDR_TV, updatedPowerStatus)); assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1); HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress); assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress); assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(updatedPowerStatus); + assertThat(cecDeviceInfo.getCecVersion()).isEqualTo( + HdmiControlManager.HDMI_CEC_VERSION_1_4_b); } @Test @@ -428,6 +435,8 @@ public class HdmiCecNetworkTest { assertThat(cecDeviceInfo.getVendorId()).isEqualTo(updatedVendorId); assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo( HdmiControlManager.POWER_STATUS_UNKNOWN); + assertThat(cecDeviceInfo.getCecVersion()).isEqualTo( + HdmiControlManager.HDMI_CEC_VERSION_1_4_b); } @Test @@ -446,4 +455,91 @@ public class HdmiCecNetworkTest { HdmiControlManager.DEVICE_EVENT_ADD_DEVICE, HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE); } + + @Test + public void cecDevices_tracking_reportPowerStatus_broadcast_infersCec2() { + int logicalAddress = Constants.ADDR_PLAYBACK_1; + int powerStatus = HdmiControlManager.POWER_STATUS_ON; + mHdmiCecNetwork.handleCecMessage( + HdmiCecMessageBuilder.buildReportPowerStatus(logicalAddress, + Constants.ADDR_BROADCAST, powerStatus)); + + assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1); + + HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress); + assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress); + assertThat(cecDeviceInfo.getPhysicalAddress()).isEqualTo( + Constants.INVALID_PHYSICAL_ADDRESS); + assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_RESERVED); + assertThat(cecDeviceInfo.getVendorId()).isEqualTo(Constants.UNKNOWN_VENDOR_ID); + assertThat(cecDeviceInfo.getDisplayName()).isEqualTo( + HdmiUtils.getDefaultDeviceName(logicalAddress)); + assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(powerStatus); + assertThat(cecDeviceInfo.getCecVersion()).isEqualTo( + HdmiControlManager.HDMI_CEC_VERSION_2_0); + } + + @Test + public void cecDevices_tracking_reportCecVersion_tracksCecVersion_cec14() { + int logicalAddress = Constants.ADDR_PLAYBACK_1; + int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b; + mHdmiCecNetwork.handleCecMessage( + HdmiCecMessageBuilder.buildCecVersion(logicalAddress, Constants.ADDR_BROADCAST, + cecVersion)); + + assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1); + + HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress); + assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress); + assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion); + } + + @Test + public void cecDevices_tracking_reportCecVersion_tracksCecVersion_cec20() { + int logicalAddress = Constants.ADDR_PLAYBACK_1; + int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0; + mHdmiCecNetwork.handleCecMessage( + HdmiCecMessageBuilder.buildCecVersion(logicalAddress, Constants.ADDR_BROADCAST, + cecVersion)); + + assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1); + + HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress); + assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress); + assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion); + } + + @Test + public void cecDevices_tracking_reportFeatures_tracksCecVersion_cec14() { + int logicalAddress = Constants.ADDR_PLAYBACK_1; + int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b; + mHdmiCecNetwork.handleCecMessage( + HdmiCecMessageBuilder.buildReportFeatures(logicalAddress, + cecVersion, Collections.emptyList(), + Constants.RC_PROFILE_SOURCE, Collections.emptyList(), + Collections.emptyList())); + + assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1); + + HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress); + assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress); + assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion); + } + + @Test + public void cecDevices_tracking_reportFeatures_tracksCecVersion_cec20() { + int logicalAddress = Constants.ADDR_PLAYBACK_1; + int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0; + mHdmiCecNetwork.handleCecMessage( + HdmiCecMessageBuilder.buildReportFeatures(logicalAddress, + cecVersion, Collections.emptyList(), + Constants.RC_PROFILE_SOURCE, Collections.emptyList(), + Collections.emptyList())); + + assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1); + + HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress); + assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress); + assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion); + } } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/OWNERS b/services/tests/servicestests/src/com/android/server/hdmi/OWNERS new file mode 100644 index 000000000000..c3c47eda59d7 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/hdmi/OWNERS @@ -0,0 +1 @@ +include /core/java/android/hardware/hdmi/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/input/OWNERS b/services/tests/servicestests/src/com/android/server/input/OWNERS new file mode 100644 index 000000000000..d701f23cb9b8 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/input/OWNERS @@ -0,0 +1 @@ +include /core/java/android/hardware/input/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/inputmethod/OWNERS b/services/tests/servicestests/src/com/android/server/inputmethod/OWNERS new file mode 100644 index 000000000000..5deb2ce8f24b --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/inputmethod/OWNERS @@ -0,0 +1 @@ +include /core/java/android/view/inputmethod/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/integrity/OWNERS b/services/tests/servicestests/src/com/android/server/integrity/OWNERS new file mode 100644 index 000000000000..653d1c969528 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/integrity/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/integrity/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/job/OWNERS b/services/tests/servicestests/src/com/android/server/job/OWNERS new file mode 100644 index 000000000000..6f207fb1a00e --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/job/OWNERS @@ -0,0 +1 @@ +include /apex/jobscheduler/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/lights/OWNERS b/services/tests/servicestests/src/com/android/server/lights/OWNERS new file mode 100644 index 000000000000..cb46a80d9b60 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/lights/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/lights/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java index 220569449ffb..25dbc6b6cd51 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java @@ -16,6 +16,9 @@ package com.android.server.locksettings; +import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH; +import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW; +import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; @@ -277,6 +280,94 @@ public class LockSettingsShellCommandTest { verify(mLockPatternUtils, never()).setLockCredential(any(), any(), anyInt()); } + @Test + public void testSetPin_nonCompliantWithComplexity() throws Exception { + when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true); + when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false); + when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true); + when(mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)).thenReturn( + PASSWORD_QUALITY_NUMERIC); + when(mLockPatternUtils.checkCredential( + LockscreenCredential.createPin("1234"), mUserId, null)).thenReturn(true); + when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId)) + .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_UNSPECIFIED)); + when(mLockPatternUtils.getRequestedPasswordComplexity(mUserId)) + .thenReturn(PASSWORD_COMPLEXITY_MEDIUM); + + assertEquals(-1, mCommand.exec(new Binder(), in, out, err, + new String[] { "set-pin", "--old", "1234", "4321" }, + mShellCallback, mResultReceiver)); + + verify(mLockPatternUtils, never()).setLockCredential(any(), any(), anyInt()); + } + + @Test + public void testSetPin_compliantWithComplexity() throws Exception { + when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true); + when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false); + when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true); + when(mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)).thenReturn( + PASSWORD_QUALITY_NUMERIC); + when(mLockPatternUtils.checkCredential( + LockscreenCredential.createPin("1234"), mUserId, null)).thenReturn(true); + when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId)) + .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_UNSPECIFIED)); + when(mLockPatternUtils.getRequestedPasswordComplexity(mUserId)) + .thenReturn(PASSWORD_COMPLEXITY_MEDIUM); + + assertEquals(0, mCommand.exec(new Binder(), in, out, err, + new String[] { "set-pin", "--old", "1234", "4231" }, + mShellCallback, mResultReceiver)); + + verify(mLockPatternUtils).setLockCredential( + LockscreenCredential.createPin("4231"), + LockscreenCredential.createPin("1234"), + mUserId); + } + + @Test + public void testSetPattern_nonCompliantWithComplexity() throws Exception { + when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true); + when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true); + when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false); + when(mLockPatternUtils.checkCredential( + LockscreenCredential.createPattern(stringToPattern("1234")), + mUserId, null)).thenReturn(true); + when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId)) + .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_UNSPECIFIED)); + when(mLockPatternUtils.getRequestedPasswordComplexity(mUserId)) + .thenReturn(PASSWORD_COMPLEXITY_HIGH); + + assertEquals(-1, mCommand.exec(new Binder(), in, out, err, + new String[] { "set-pattern", "--old", "1234", "4321" }, + mShellCallback, mResultReceiver)); + + verify(mLockPatternUtils, never()).setLockCredential(any(), any(), anyInt()); + } + + @Test + public void testSetPattern_compliantWithComplexity() throws Exception { + when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true); + when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true); + when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false); + when(mLockPatternUtils.checkCredential( + LockscreenCredential.createPattern(stringToPattern("1234")), + mUserId, null)).thenReturn(true); + when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId)) + .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_UNSPECIFIED)); + when(mLockPatternUtils.getRequestedPasswordComplexity(mUserId)) + .thenReturn(PASSWORD_COMPLEXITY_LOW); + + assertEquals(0, mCommand.exec(new Binder(), in, out, err, + new String[] { "set-pattern", "--old", "1234", "4321" }, + mShellCallback, mResultReceiver)); + + verify(mLockPatternUtils).setLockCredential( + LockscreenCredential.createPattern(stringToPattern("4321")), + LockscreenCredential.createPattern(stringToPattern("1234")), + mUserId); + } + private List<LockPatternView.Cell> stringToPattern(String str) { return LockPatternUtils.byteArrayToPattern(str.getBytes()); } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/OWNERS b/services/tests/servicestests/src/com/android/server/locksettings/OWNERS new file mode 100644 index 000000000000..0a8dc8c45a9f --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/locksettings/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/locksettings/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java index 7767a2810ac2..9d300a611374 100644 --- a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java @@ -20,11 +20,11 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; +import android.net.InetAddresses; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; import android.net.LinkAddress; -import android.net.NetworkUtils; import android.net.ProxyInfo; import android.net.StaticIpConfiguration; import android.util.ArrayMap; @@ -79,8 +79,8 @@ public class IpConfigStoreTest { StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration(); staticIpConfiguration.ipAddress = new LinkAddress(IP_ADDR_1); - staticIpConfiguration.dnsServers.add(NetworkUtils.numericToInetAddress(DNS_IP_ADDR_1)); - staticIpConfiguration.dnsServers.add(NetworkUtils.numericToInetAddress(DNS_IP_ADDR_2)); + staticIpConfiguration.dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_1)); + staticIpConfiguration.dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_2)); ProxyInfo proxyInfo = new ProxyInfo("10.10.10.10", 88, "host1,host2"); diff --git a/services/tests/servicestests/src/com/android/server/net/OWNERS b/services/tests/servicestests/src/com/android/server/net/OWNERS new file mode 100644 index 000000000000..aa87958f1d53 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/net/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/net/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/om/OWNERS b/services/tests/servicestests/src/com/android/server/om/OWNERS new file mode 100644 index 000000000000..afb98d416762 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/om/OWNERS @@ -0,0 +1 @@ +include /core/java/android/content/om/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/people/OWNERS b/services/tests/servicestests/src/com/android/server/people/OWNERS new file mode 100644 index 000000000000..3198a5e84307 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/people/OWNERS @@ -0,0 +1 @@ +include /services/people/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/pm/OWNERS b/services/tests/servicestests/src/com/android/server/pm/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pm/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/policy/OWNERS b/services/tests/servicestests/src/com/android/server/policy/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/policy/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/power/OWNERS b/services/tests/servicestests/src/com/android/server/power/OWNERS new file mode 100644 index 000000000000..d68066bb8c40 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/power/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/power/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/powerstats/OWNERS b/services/tests/servicestests/src/com/android/server/powerstats/OWNERS new file mode 100644 index 000000000000..d68066bb8c40 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/powerstats/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/power/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/rollback/OWNERS b/services/tests/servicestests/src/com/android/server/rollback/OWNERS new file mode 100644 index 000000000000..d04a70619caa --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/rollback/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/rollback/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS new file mode 100644 index 000000000000..816bc6bba639 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS @@ -0,0 +1 @@ +include /core/java/android/media/soundtrigger/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/stats/OWNERS b/services/tests/servicestests/src/com/android/server/stats/OWNERS new file mode 100644 index 000000000000..ee865b1e4ec8 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/stats/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/stats/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/storage/OWNERS b/services/tests/servicestests/src/com/android/server/storage/OWNERS new file mode 100644 index 000000000000..6f9dbea36b06 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/storage/OWNERS @@ -0,0 +1 @@ +include /core/java/android/os/storage/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/textclassifier/OWNERS b/services/tests/servicestests/src/com/android/server/textclassifier/OWNERS new file mode 100644 index 000000000000..46b3cb8824a0 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/textclassifier/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/textclassifier/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/timedetector/OWNERS b/services/tests/servicestests/src/com/android/server/timedetector/OWNERS new file mode 100644 index 000000000000..09447a971bdd --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/timedetector/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/timezone/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/timezone/OWNERS b/services/tests/servicestests/src/com/android/server/timezone/OWNERS new file mode 100644 index 000000000000..09447a971bdd --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/timezone/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/timezone/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS b/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS new file mode 100644 index 000000000000..09447a971bdd --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/timezone/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/tv/OWNERS b/services/tests/servicestests/src/com/android/server/tv/OWNERS new file mode 100644 index 000000000000..305027ce077f --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/tv/OWNERS @@ -0,0 +1 @@ +include /media/java/android/media/tv/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/uri/OWNERS b/services/tests/servicestests/src/com/android/server/uri/OWNERS new file mode 100644 index 000000000000..ca5d5f9803e3 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/uri/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/uri/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/usage/OWNERS b/services/tests/servicestests/src/com/android/server/usage/OWNERS new file mode 100644 index 000000000000..d3227de87684 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/usage/OWNERS @@ -0,0 +1 @@ +include /services/usage/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/vibrator/OWNERS b/services/tests/servicestests/src/com/android/server/vibrator/OWNERS new file mode 100644 index 000000000000..cc63ceb2c7ad --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/vibrator/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/vibrator/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java index fa171fdeaece..1a4ac0777ba5 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java @@ -28,6 +28,7 @@ import android.content.Context; import android.content.ContextWrapper; import android.os.Handler; import android.os.IExternalVibratorService; +import android.os.PowerManagerInternal; import android.os.UserHandle; import android.os.VibrationAttributes; import android.os.VibrationEffect; @@ -40,7 +41,9 @@ import androidx.test.InstrumentationRegistry; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProviderRule; +import com.android.server.LocalServices; +import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -62,6 +65,7 @@ public class VibrationScalerTest { // TODO(b/131311651): replace with a FakeVibrator instead. @Mock private Vibrator mVibratorMock; + @Mock private PowerManagerInternal mPowerManagerInternalMock; private TestLooper mTestLooper; private ContextWrapper mContextSpy; @@ -77,11 +81,19 @@ public class VibrationScalerTest { when(mContextSpy.getContentResolver()).thenReturn(contentResolver); when(mContextSpy.getSystemService(eq(Context.VIBRATOR_SERVICE))).thenReturn(mVibratorMock); + LocalServices.removeServiceForTest(PowerManagerInternal.class); + LocalServices.addService(PowerManagerInternal.class, mPowerManagerInternalMock); + mVibrationSettings = new VibrationSettings( mContextSpy, new Handler(mTestLooper.getLooper())); mVibrationScaler = new VibrationScaler(mContextSpy, mVibrationSettings); } + @After + public void tearDown() throws Exception { + LocalServices.removeServiceForTest(PowerManagerInternal.class); + } + @Test public void testGetExternalVibrationScale() { when(mVibratorMock.getDefaultHapticFeedbackIntensity()) diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java index 04c2cb3b1148..ecdb8bc71bd8 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java @@ -20,7 +20,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -32,6 +34,9 @@ import android.content.Context; import android.content.ContextWrapper; import android.media.AudioManager; import android.os.Handler; +import android.os.PowerManagerInternal; +import android.os.PowerSaveState; +import android.os.RemoteException; import android.os.UserHandle; import android.os.VibrationAttributes; import android.os.VibrationEffect; @@ -44,6 +49,7 @@ import androidx.test.InstrumentationRegistry; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProviderRule; +import com.android.server.LocalServices; import org.junit.After; import org.junit.Before; @@ -62,17 +68,24 @@ import org.mockito.junit.MockitoRule; @Presubmit public class VibrationSettingsTest { + private static final int UID = 1; + private static final PowerSaveState NORMAL_POWER_STATE = new PowerSaveState.Builder().build(); + private static final PowerSaveState LOW_POWER_STATE = new PowerSaveState.Builder() + .setBatterySaverEnabled(true).build(); + @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule(); // TODO(b/131311651): replace with a FakeVibrator instead. @Mock private Vibrator mVibratorMock; @Mock private VibrationSettings.OnVibratorSettingsChanged mListenerMock; + @Mock private PowerManagerInternal mPowerManagerInternalMock; private TestLooper mTestLooper; private ContextWrapper mContextSpy; private AudioManager mAudioManager; private VibrationSettings mVibrationSettings; + private PowerManagerInternal.LowPowerModeListener mRegisteredPowerModeListener; @Before public void setUp() throws Exception { @@ -83,10 +96,17 @@ public class VibrationSettingsTest { when(mContextSpy.getContentResolver()).thenReturn(contentResolver); when(mContextSpy.getSystemService(eq(Context.VIBRATOR_SERVICE))).thenReturn(mVibratorMock); when(mVibratorMock.hasVibrator()).thenReturn(true); + doAnswer(invocation -> { + mRegisteredPowerModeListener = invocation.getArgument(0); + return null; + }).when(mPowerManagerInternalMock).registerLowPowerModeObserver(any()); + + LocalServices.removeServiceForTest(PowerManagerInternal.class); + LocalServices.addService(PowerManagerInternal.class, mPowerManagerInternalMock); mAudioManager = mContextSpy.getSystemService(AudioManager.class); - mVibrationSettings = new VibrationSettings( - mContextSpy, new Handler(mTestLooper.getLooper())); + mVibrationSettings = new VibrationSettings(mContextSpy, + new Handler(mTestLooper.getLooper())); setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0); setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0); @@ -96,7 +116,7 @@ public class VibrationSettingsTest { @After public void tearDown() throws Exception { - FakeSettingsProvider.clearSettingsProvider(); + LocalServices.removeServiceForTest(PowerManagerInternal.class); } @Test @@ -118,6 +138,17 @@ public class VibrationSettingsTest { } @Test + public void addListener_lowPowerModeChangeTriggerListener() { + mVibrationSettings.addListener(mListenerMock); + + mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE); + mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE); + mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE); // No change. + + verify(mListenerMock, times(2)).onChange(); + } + + @Test public void removeListener_noMoreCallbacksToListener() { mVibrationSettings.addListener(mListenerMock); @@ -132,56 +163,103 @@ public class VibrationSettingsTest { } @Test - public void shouldVibrateForRingtones_withVibrateWhenRinging_onlyIgnoreSettingsForSilentMode() { + public void shouldVibrateForRingerMode_withoutRingtoneUsage_returnsTrue() { + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(VibrationAttributes.USAGE_ALARM)); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(VibrationAttributes.USAGE_TOUCH)); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode( + VibrationAttributes.USAGE_NOTIFICATION)); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode( + VibrationAttributes.USAGE_COMMUNICATION_REQUEST)); + } + + @Test + public void shouldVibrateForRingerMode_withVibrateWhenRinging_ignoreSettingsForSilentMode() { + int usageRingtone = VibrationAttributes.USAGE_RINGTONE; setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1); setRingerMode(AudioManager.RINGER_MODE_SILENT); - assertFalse(mVibrationSettings.shouldVibrateForRingtone()); + assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_MAX); - assertTrue(mVibrationSettings.shouldVibrateForRingtone()); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_NORMAL); - assertTrue(mVibrationSettings.shouldVibrateForRingtone()); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_VIBRATE); - assertTrue(mVibrationSettings.shouldVibrateForRingtone()); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); } @Test - public void shouldVibrateForRingtones_withApplyRampingRinger_onlyIgnoreSettingsForSilentMode() { + public void shouldVibrateForRingerMode_withApplyRampingRinger_ignoreSettingsForSilentMode() { + int usageRingtone = VibrationAttributes.USAGE_RINGTONE; setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0); setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 1); setRingerMode(AudioManager.RINGER_MODE_SILENT); - assertFalse(mVibrationSettings.shouldVibrateForRingtone()); + assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_MAX); - assertTrue(mVibrationSettings.shouldVibrateForRingtone()); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_NORMAL); - assertTrue(mVibrationSettings.shouldVibrateForRingtone()); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_VIBRATE); - assertTrue(mVibrationSettings.shouldVibrateForRingtone()); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); } @Test - public void shouldVibrateForRingtones_withAllSettingsOff_onlyVibratesForVibrateMode() { + public void shouldVibrateForRingerMode_withAllSettingsOff_onlyVibratesForVibrateMode() { + int usageRingtone = VibrationAttributes.USAGE_RINGTONE; setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0); setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0); setRingerMode(AudioManager.RINGER_MODE_VIBRATE); - assertTrue(mVibrationSettings.shouldVibrateForRingtone()); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_SILENT); - assertFalse(mVibrationSettings.shouldVibrateForRingtone()); + assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_MAX); - assertFalse(mVibrationSettings.shouldVibrateForRingtone()); + assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_NORMAL); - assertFalse(mVibrationSettings.shouldVibrateForRingtone()); + assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); + } + + @Test + public void shouldVibrateForUid_withBackgroundAllowedUsage_returnTrue() throws RemoteException { + assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_ALARM)); + assertTrue(mVibrationSettings.shouldVibrateForUid(UID, + VibrationAttributes.USAGE_NOTIFICATION)); + assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_RINGTONE)); + } + + @Test + public void shouldVibrateForPowerMode_withLowPowerAndAllowedUsage_returnTrue() { + mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE); + + assertTrue(mVibrationSettings.shouldVibrateForPowerMode(VibrationAttributes.USAGE_ALARM)); + assertTrue(mVibrationSettings.shouldVibrateForPowerMode( + VibrationAttributes.USAGE_RINGTONE)); + assertTrue(mVibrationSettings.shouldVibrateForPowerMode( + VibrationAttributes.USAGE_COMMUNICATION_REQUEST)); + } + + @Test + public void shouldVibrateForPowerMode_withRestrictedUsage_returnsFalseWhileInLowPowerMode() { + mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE); + + assertTrue(mVibrationSettings.shouldVibrateForPowerMode(VibrationAttributes.USAGE_TOUCH)); + assertTrue(mVibrationSettings.shouldVibrateForPowerMode( + VibrationAttributes.USAGE_NOTIFICATION)); + + mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE); + + assertFalse(mVibrationSettings.shouldVibrateForPowerMode(VibrationAttributes.USAGE_TOUCH)); + assertFalse(mVibrationSettings.shouldVibrateForPowerMode( + VibrationAttributes.USAGE_NOTIFICATION)); } @Test @@ -299,4 +377,5 @@ public class VibrationSettingsTest { mAudioManager.setRingerModeInternal(ringerMode); assertEquals(ringerMode, mAudioManager.getRingerModeInternal()); } + } diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java index 1f163bd3282b..815aa8ee66ae 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java @@ -16,7 +16,6 @@ package com.android.server.vibrator; -import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -38,7 +37,6 @@ import android.hardware.vibrator.IVibrator; import android.os.IBinder; import android.os.IVibratorStateListener; import android.os.VibrationEffect; -import android.os.Vibrator; import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; @@ -100,7 +98,7 @@ public class VibratorControllerTest { public void createController_initializesNativeWrapper() { int vibratorId = 13; VibratorController controller = createController(vibratorId); - assertEquals(vibratorId, controller.getVibratorId()); + assertEquals(vibratorId, controller.getVibratorInfo().getId()); verify(mNativeWrapperMock).init(eq(vibratorId), notNull()); } @@ -132,59 +130,6 @@ public class VibratorControllerTest { } @Test - public void areEffectsSupported_withNullResultFromNative_returnsSupportUnknown() { - when(mNativeWrapperMock.getSupportedEffects()).thenReturn(null); - assertArrayEquals(new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN}, - createController().areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK})); - } - - @Test - public void areEffectsSupported_withSomeEffectsSupported_returnsSupportYesAndNoForEffects() { - int[] effects = new int[]{VibrationEffect.EFFECT_CLICK, VibrationEffect.EFFECT_TICK}; - - when(mNativeWrapperMock.getSupportedEffects()) - .thenReturn(new int[]{VibrationEffect.EFFECT_CLICK}); - assertArrayEquals( - new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_YES, - Vibrator.VIBRATION_EFFECT_SUPPORT_NO}, - createController().areEffectsSupported(effects)); - } - - @Test - public void arePrimitivesSupported_withoutComposeCapability_returnsAlwaysFalse() { - assertArrayEquals(new boolean[]{false, false}, - createController().arePrimitivesSupported(new int[]{ - VibrationEffect.Composition.PRIMITIVE_CLICK, - VibrationEffect.Composition.PRIMITIVE_TICK - })); - } - - @Test - public void arePrimitivesSupported_withNullResultFromNative_returnsAlwaysFalse() { - mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); - when(mNativeWrapperMock.getSupportedPrimitives()).thenReturn(null); - - assertArrayEquals(new boolean[]{false, false}, - createController().arePrimitivesSupported(new int[]{ - VibrationEffect.Composition.PRIMITIVE_CLICK, - VibrationEffect.Composition.PRIMITIVE_QUICK_RISE - })); - } - - @Test - public void arePrimitivesSupported_withSomeSupportedPrimitives_returnsBasedOnNativeResult() { - mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); - when(mNativeWrapperMock.getSupportedPrimitives()) - .thenReturn(new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}); - - assertArrayEquals(new boolean[]{true, false}, - createController().arePrimitivesSupported(new int[]{ - VibrationEffect.Composition.PRIMITIVE_CLICK, - VibrationEffect.Composition.PRIMITIVE_QUICK_RISE - })); - } - - @Test public void setExternalControl_withCapability_enablesExternalControl() { mockVibratorCapabilities(IVibrator.CAP_EXTERNAL_CONTROL); VibratorController controller = createController(); diff --git a/services/tests/servicestests/src/com/android/server/wallpaper/OWNERS b/services/tests/servicestests/src/com/android/server/wallpaper/OWNERS new file mode 100644 index 000000000000..8ff0f74202f8 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/wallpaper/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/wallpaper/OWNERS diff --git a/services/tests/servicestests/test-apps/JobTestApp/OWNERS b/services/tests/servicestests/test-apps/JobTestApp/OWNERS new file mode 100644 index 000000000000..6f207fb1a00e --- /dev/null +++ b/services/tests/servicestests/test-apps/JobTestApp/OWNERS @@ -0,0 +1 @@ +include /apex/jobscheduler/OWNERS diff --git a/services/tests/servicestests/test-apps/PackageParserApp/OWNERS b/services/tests/servicestests/test-apps/PackageParserApp/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/services/tests/servicestests/test-apps/PackageParserApp/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/services/tests/servicestests/test-apps/PackageParsingTestManifests/OWNERS b/services/tests/servicestests/test-apps/PackageParsingTestManifests/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/services/tests/servicestests/test-apps/PackageParsingTestManifests/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/services/tests/uiservicestests/src/com/android/server/OWNERS b/services/tests/uiservicestests/src/com/android/server/OWNERS new file mode 100644 index 000000000000..05944c03c638 --- /dev/null +++ b/services/tests/uiservicestests/src/com/android/server/OWNERS @@ -0,0 +1 @@ +per-file UiModeManagerServiceTest.java = file:/packages/SystemUI/OWNERS diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java index 4a4d9bc174fb..ec28baf53d3c 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java @@ -249,13 +249,13 @@ public class ManagedServicesTest extends UiServiceTestCase { backupPrimary.get(approvalLevel).get(userId), Build.VERSION_CODES.N_MR1, userId); } - verifyExpectedApprovedEntries(service, true); for (int userId : backupSecondary.get(approvalLevel).keySet()) { service.onSettingRestored(service.getConfig().secondarySettingName, backupSecondary.get(approvalLevel).get(userId), Build.VERSION_CODES.N_MR1, userId); } + // both sets of approved entries should be allowed verifyExpectedApprovedEntries(service); verifyExpectedApprovedEntries(service, backupPrimary.get(approvalLevel)); verifyExpectedApprovedEntries(service, backupSecondary.get(approvalLevel)); @@ -638,8 +638,8 @@ public class ManagedServicesTest extends UiServiceTestCase { @Test public void testWriteXml_writesSetting() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { - ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, - mIpm, approvalLevel); + ManagedServices service = new TestManagedServicesSettings(getContext(), mLock, + mUserProfiles, mIpm, approvalLevel); loadXml(service); TypedXmlSerializer serializer = Xml.newFastSerializer(); @@ -662,6 +662,36 @@ public class ManagedServicesTest extends UiServiceTestCase { } @Test + public void testWriteXml_doesNotWriteSetting() throws Exception { + for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { + ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, + mIpm, approvalLevel); + + for (int userId : mUserProfiles.getCurrentProfileIds().toArray()) { + Settings.Secure.putStringForUser( + getContext().getContentResolver(), + service.getConfig().secureSettingName, null, userId); + } + loadXml(service); + + TypedXmlSerializer serializer = Xml.newFastSerializer(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); + serializer.startDocument(null, true); + service.writeXml(serializer, false, UserHandle.USER_ALL); + serializer.endDocument(); + serializer.flush(); + + for (int userId : mUserProfiles.getCurrentProfileIds().toArray()) { + String actual = Settings.Secure.getStringForUser( + getContext().getContentResolver(), + service.getConfig().secureSettingName, userId); + assertTrue(TextUtils.isEmpty(actual)); + } + } + } + + @Test public void testWriteXml_writesUserSet() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, @@ -1415,11 +1445,11 @@ public class ManagedServicesTest extends UiServiceTestCase { xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " " + ManagedServices.ATT_USER_ID + "=\"99\" " + ManagedServices.ATT_IS_PRIMARY + "=\"true\" " - + ManagedServices.ATT_APPROVED_LIST + "=\"99\" />\n"); + + ManagedServices.ATT_APPROVED_LIST + "=\"990\" />\n"); xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " " + ManagedServices.ATT_USER_ID + "=\"98\" " + ManagedServices.ATT_IS_PRIMARY + "=\"false\" " - + ManagedServices.ATT_APPROVED_LIST + "=\"98\" />\n"); + + ManagedServices.ATT_APPROVED_LIST + "=\"981\" />\n"); xml.append("</" + xmlTag + ">"); return xml.toString(); @@ -1483,7 +1513,7 @@ public class ManagedServicesTest extends UiServiceTestCase { private void assertContentsInAnyOrder(Collection<?> expected, Collection<?> actual) { assertNotNull(actual); - assertEquals(expected.size(), actual.size()); + assertEquals(expected + " : " + actual, expected.size(), actual.size()); for (Object o : expected) { assertTrue("Actual missing " + o, actual.contains(o)); @@ -1665,4 +1695,17 @@ public class ManagedServicesTest extends UiServiceTestCase { return null; } } + + class TestManagedServicesSettings extends TestManagedServices { + + public TestManagedServicesSettings(Context context, Object mutex, UserProfiles userProfiles, + IPackageManager pm, int approvedServiceType) { + super(context, mutex, userProfiles, pm, approvedServiceType); + } + + @Override + public boolean shouldReflectToSettings() { + return true; + } + } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java index e658d179f4f3..18ca09be235c 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java @@ -126,6 +126,7 @@ public class NotificationAdjustmentExtractorTest extends UiServiceTestCase { return new Notification.Action.Builder( Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon), "action", - PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0)).build(); + PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), + PendingIntent.FLAG_IMMUTABLE)).build(); } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java index 00d93ded9a3c..ac9a77bc5cb7 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java @@ -59,7 +59,8 @@ public class NotificationIntrusivenessExtractorTest extends UiServiceTestCase { final Notification.Builder builder = new Notification.Builder(getContext()) .setContentTitle("foo") .setFullScreenIntent(PendingIntent.getActivity( - getContext(), 0, new Intent(""), 0), true) + getContext(), 0, new Intent(""), PendingIntent.FLAG_IMMUTABLE), + true) .setSmallIcon(android.R.drawable.sym_def_app_icon); Notification n = builder.build(); @@ -77,7 +78,8 @@ public class NotificationIntrusivenessExtractorTest extends UiServiceTestCase { final Notification.Builder builder = new Notification.Builder(getContext()) .setContentTitle("foo") .setFullScreenIntent(PendingIntent.getActivity( - getContext(), 0, new Intent(""), 0), true) + getContext(), 0, new Intent(""), PendingIntent.FLAG_IMMUTABLE), + true) .setSmallIcon(android.R.drawable.sym_def_app_icon); Notification n = builder.build(); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java index 9b37e76e4c65..be489c3bcd12 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java @@ -361,7 +361,7 @@ public class NotificationListenerServiceTest extends UiServiceTestCase { getContext(), index /*requestCode*/, new Intent("ACTION_" + key), - 0 /*flags*/); + PendingIntent.FLAG_IMMUTABLE /*flags*/); actions.add(new Notification.Action.Builder(null /*icon*/, key, intent).build()); } return actions; diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 762ec93712cb..b354a890a721 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -790,7 +790,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { .setName("bubblebot") .build(); RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); - PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); + PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), + PendingIntent.FLAG_MUTABLE); Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", inputIntent).addRemoteInput(remoteInput) @@ -4977,6 +4978,40 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testCustomToastPostedWhileInForeground_blockedIfAppGoesToBackground() + throws Exception { + final String testPackage = "testPackageName"; + assertEquals(0, mService.mToastQueue.size()); + mService.isSystemUid = false; + setToastRateIsWithinQuota(true); + + // package is not suspended + when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) + .thenReturn(false); + + setAppInForegroundForToasts(mUid, true); + + Binder token1 = new Binder(); + Binder token2 = new Binder(); + ITransientNotification callback1 = mock(ITransientNotification.class); + ITransientNotification callback2 = mock(ITransientNotification.class); + INotificationManager nmService = (INotificationManager) mService.mService; + + nmService.enqueueToast(testPackage, token1, callback1, 2000, 0); + nmService.enqueueToast(testPackage, token2, callback2, 2000, 0); + + assertEquals(2, mService.mToastQueue.size()); // Both toasts enqueued. + verify(callback1, times(1)).show(any()); // First toast shown. + + setAppInForegroundForToasts(mUid, false); + + mService.cancelToastLocked(0); // Remove the first toast, and show next. + + assertEquals(0, mService.mToastQueue.size()); // Both toasts processed. + verify(callback2, never()).show(any()); // Second toast was never shown. + } + + @Test public void testAllowForegroundTextToasts() throws Exception { final String testPackage = "testPackageName"; assertEquals(0, mService.mToastQueue.size()); @@ -7366,7 +7401,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); ArrayList<Notification.Action> extraAction = new ArrayList<>(); RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); - PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); + PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), + PendingIntent.FLAG_IMMUTABLE); Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", inputIntent).addRemoteInput(remoteInput) @@ -7396,7 +7432,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); ArrayList<Notification.Action> extraAction = new ArrayList<>(); RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); - PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); + PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), + PendingIntent.FLAG_MUTABLE); Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", inputIntent).addRemoteInput(remoteInput) diff --git a/services/tests/uiservicestests/src/com/android/server/notification/OWNERS b/services/tests/uiservicestests/src/com/android/server/notification/OWNERS new file mode 100644 index 000000000000..396fd1213aca --- /dev/null +++ b/services/tests/uiservicestests/src/com/android/server/notification/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/notification/OWNERS diff --git a/services/tests/uiservicestests/src/com/android/server/slice/OWNERS b/services/tests/uiservicestests/src/com/android/server/slice/OWNERS new file mode 100644 index 000000000000..3d0859f6f701 --- /dev/null +++ b/services/tests/uiservicestests/src/com/android/server/slice/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/slice/OWNERS diff --git a/services/tests/wmtests/OWNERS b/services/tests/wmtests/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/services/tests/wmtests/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java index e47913fba7ab..8e78dce39ac7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java @@ -40,6 +40,7 @@ import static com.android.server.wm.DisplayAreaPolicyBuilder.Feature; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.testng.Assert.assertThrows; @@ -100,6 +101,7 @@ public class DisplayAreaPolicyBuilderTest { mRoot = new SurfacelessDisplayAreaRoot(mWms); mImeContainer = new DisplayArea.Tokens(mWms, ABOVE_TASKS, "ImeContainer"); mDisplayContent = mock(DisplayContent.class); + doReturn(true).when(mDisplayContent).isTrusted(); mDefaultTaskDisplayArea = new TaskDisplayArea(mDisplayContent, mWms, "Tasks", FEATURE_DEFAULT_TASK_CONTAINER); mTaskDisplayAreaList = new ArrayList<>(); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java index 496b2b744712..d451180c7269 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java @@ -22,15 +22,18 @@ import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.DisplayArea.Type.ABOVE_TASKS; import static com.android.server.wm.WindowContainer.POSITION_BOTTOM; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import android.platform.test.annotations.Presubmit; +import android.util.Pair; +import android.view.Display; +import android.view.DisplayInfo; import androidx.test.filters.SmallTest; @@ -38,9 +41,8 @@ import com.android.server.wm.DisplayAreaPolicyBuilderTest.SurfacelessDisplayArea import com.google.android.collect.Lists; -import org.junit.Before; -import org.junit.Rule; import org.junit.Test; +import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.Collections; @@ -54,78 +56,65 @@ import java.util.List; */ @SmallTest @Presubmit -public class DisplayAreaPolicyTests { - - @Rule - public final SystemServicesTestRule mSystemServices = new SystemServicesTestRule(); - - private DisplayAreaPolicyBuilder.Result mPolicy; - private TaskDisplayArea mTaskDisplayArea1; - private TaskDisplayArea mTaskDisplayArea2; - private RootDisplayArea mRoot; - - @Before - public void setUp() throws Exception { - WindowManagerService wms = mSystemServices.getWindowManagerService(); - mRoot = new SurfacelessDisplayAreaRoot(wms); - spyOn(mRoot); - DisplayArea.Tokens ime = new DisplayArea.Tokens(wms, ABOVE_TASKS, "Ime"); - DisplayContent displayContent = mock(DisplayContent.class); - doReturn(true).when(displayContent).isTrusted(); - mTaskDisplayArea1 = new TaskDisplayArea(displayContent, wms, "Tasks1", - FEATURE_DEFAULT_TASK_CONTAINER); - mTaskDisplayArea2 = new TaskDisplayArea(displayContent, wms, "Tasks2", - FEATURE_VENDOR_FIRST); - List<TaskDisplayArea> taskDisplayAreaList = new ArrayList<>(); - taskDisplayAreaList.add(mTaskDisplayArea1); - taskDisplayAreaList.add(mTaskDisplayArea2); - - mPolicy = new DisplayAreaPolicyBuilder() - .setRootHierarchy(new DisplayAreaPolicyBuilder.HierarchyBuilder(mRoot) - .setImeContainer(ime) - .setTaskDisplayAreas(taskDisplayAreaList)) - .build(wms); - } +@RunWith(WindowTestRunner.class) +public class DisplayAreaPolicyTests extends WindowTestsBase { @Test public void testGetDefaultTaskDisplayArea() { - assertEquals(mTaskDisplayArea1, mPolicy.getDefaultTaskDisplayArea()); + final Pair<DisplayAreaPolicy, List<TaskDisplayArea>> result = + createPolicyWith2TaskDisplayAreas(); + final DisplayAreaPolicy policy = result.first; + final TaskDisplayArea taskDisplayArea1 = result.second.get(0); + assertEquals(taskDisplayArea1, policy.getDefaultTaskDisplayArea()); } @Test public void testTaskDisplayArea_taskPositionChanged_updatesTaskDisplayAreaPosition() { - final Task stack1 = mTaskDisplayArea1.createRootTask( + final Pair<DisplayAreaPolicy, List<TaskDisplayArea>> result = + createPolicyWith2TaskDisplayAreas(); + final DisplayAreaPolicy policy = result.first; + final TaskDisplayArea taskDisplayArea1 = result.second.get(0); + final TaskDisplayArea taskDisplayArea2 = result.second.get(1); + final Task stack1 = taskDisplayArea1.createRootTask( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); - final Task stack2 = mTaskDisplayArea2.createRootTask( + final Task stack2 = taskDisplayArea2.createRootTask( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); // Initial order - assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea1, mTaskDisplayArea2); + assertTaskDisplayAreasOrder(policy, taskDisplayArea1, taskDisplayArea2); // Move stack in tda1 to top stack1.getParent().positionChildAt(POSITION_TOP, stack1, true /* includingParents */); - assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea2, mTaskDisplayArea1); + assertTaskDisplayAreasOrder(policy, taskDisplayArea2, taskDisplayArea1); // Move stack in tda2 to top, but not including parents stack2.getParent().positionChildAt(POSITION_TOP, stack2, false /* includingParents */); - assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea2, mTaskDisplayArea1); + assertTaskDisplayAreasOrder(policy, taskDisplayArea2, taskDisplayArea1); // Move stack in tda1 to bottom stack1.getParent().positionChildAt(POSITION_BOTTOM, stack1, true /* includingParents */); - assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea1, mTaskDisplayArea2); + assertTaskDisplayAreasOrder(policy, taskDisplayArea1, taskDisplayArea2); // Move stack in tda2 to bottom, but not including parents stack2.getParent().positionChildAt(POSITION_BOTTOM, stack2, false /* includingParents */); - assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea1, mTaskDisplayArea2); + assertTaskDisplayAreasOrder(policy, taskDisplayArea1, taskDisplayArea2); + } + + @Test + public void testEmptyFeaturesOnUntrustedDisplay() { + final DisplayInfo info = new DisplayInfo(mDisplayInfo); + info.flags &= ~Display.FLAG_TRUSTED; + final DisplayContent untrustedDisplay = new TestDisplayContent.Builder(mAtm, info).build(); + assertTrue(untrustedDisplay.mFeatures.isEmpty()); } @Test public void testDisplayAreaGroup_taskPositionChanged_updatesDisplayAreaGroupPosition() { - final WindowManagerService wms = mSystemServices.getWindowManagerService(); + final WindowManagerService wms = mWm; final DisplayContent displayContent = mock(DisplayContent.class); doReturn(true).when(displayContent).isTrusted(); final RootDisplayArea root = new SurfacelessDisplayAreaRoot(wms); @@ -203,4 +192,24 @@ public class DisplayAreaPolicyTests { }, false /* traverseTopToBottom */); assertEquals(expectOrder, actualOrder); } + + private Pair<DisplayAreaPolicy, List<TaskDisplayArea>> createPolicyWith2TaskDisplayAreas() { + final SurfacelessDisplayAreaRoot root = new SurfacelessDisplayAreaRoot(mWm); + final DisplayArea.Tokens ime = new DisplayArea.Tokens(mWm, ABOVE_TASKS, "Ime"); + final DisplayContent displayContent = mock(DisplayContent.class); + doReturn(true).when(displayContent).isTrusted(); + final TaskDisplayArea taskDisplayArea1 = new TaskDisplayArea(displayContent, mWm, "Tasks1", + FEATURE_DEFAULT_TASK_CONTAINER); + final TaskDisplayArea taskDisplayArea2 = new TaskDisplayArea(displayContent, mWm, "Tasks2", + FEATURE_VENDOR_FIRST); + final List<TaskDisplayArea> taskDisplayAreaList = new ArrayList<>(); + taskDisplayAreaList.add(taskDisplayArea1); + taskDisplayAreaList.add(taskDisplayArea2); + + return Pair.create(new DisplayAreaPolicyBuilder() + .setRootHierarchy(new DisplayAreaPolicyBuilder.HierarchyBuilder(root) + .setImeContainer(ime) + .setTaskDisplayAreas(taskDisplayAreaList)) + .build(mWm), taskDisplayAreaList); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java index 5c39bd0a316b..6dd23ba02e9a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java @@ -423,6 +423,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { final WindowState homeWindow = createWindow(null, TYPE_BASE_APPLICATION, homeActivity, "homeWindow"); + makeWindowVisible(homeWindow); homeActivity.addWindow(homeWindow); homeWindow.getAttrs().flags |= FLAG_SHOW_WALLPAPER; diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java index 0bb2867fa690..ec65085ea4a8 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java @@ -30,6 +30,8 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.app.WindowConfiguration; @@ -183,6 +185,24 @@ public class TaskSnapshotControllerTest extends WindowTestsBase { } } + @UseTestDisplay(addWindows = {W_ACTIVITY, W_INPUT_METHOD}) + @Test + public void testCreateTaskSnapshotWithExcludingIme() { + Task task = mAppWindow.mActivityRecord.getTask(); + spyOn(task); + spyOn(mDisplayContent); + when(task.getDisplayContent().isImeAttachedToApp()).thenReturn(false); + // Intentionally set the SurfaceControl of input method window as null. + mDisplayContent.mInputMethodWindow.setSurfaceControl(null); + // Verify no NPE happens when calling createTaskSnapshot. + try { + mWm.mTaskSnapshotController.createTaskSnapshot(mAppWindow.mActivityRecord.getTask(), + 1f /* scaleFraction */, PixelFormat.UNKNOWN, null /* outTaskSize */); + } catch (NullPointerException e) { + fail("There should be no exception when calling createTaskSnapshot"); + } + } + @UseTestDisplay(addWindows = W_ACTIVITY) @Test public void testPrepareTaskSnapshot() { diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index 227eba2a041b..a57de094a210 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -19,9 +19,10 @@ package com.android.server.wm; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; -import static android.hardware.camera2.params.OutputConfiguration.ROTATION_90; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.Surface.ROTATION_0; +import static android.view.Surface.ROTATION_270; +import static android.view.Surface.ROTATION_90; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; @@ -480,33 +481,49 @@ public class WindowStateTests extends WindowTestsBase { final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); final SurfaceControl.Transaction t = spy(StubTransaction.class); - app.mHasSurface = true; + makeWindowVisible(app); app.mSurfaceControl = mock(SurfaceControl.class); - try { - app.getFrame().set(10, 20, 60, 80); - app.updateSurfacePosition(t); - - app.seamlesslyRotateIfAllowed(t, ROTATION_0, ROTATION_90, true); - - assertTrue(app.mSeamlesslyRotated); - - // Verify we un-rotate the window state surface. - Matrix matrix = new Matrix(); - // Un-rotate 90 deg - matrix.setRotate(270); - // Translate it back to origin - matrix.postTranslate(0, mDisplayInfo.logicalWidth); - verify(t).setMatrix(eq(app.mSurfaceControl), eq(matrix), any(float[].class)); - - // Verify we update the position as well. - float[] currentSurfacePos = {app.mLastSurfacePosition.x, app.mLastSurfacePosition.y}; - matrix.mapPoints(currentSurfacePos); - verify(t).setPosition(eq(app.mSurfaceControl), eq(currentSurfacePos[0]), - eq(currentSurfacePos[1])); - } finally { - app.mSurfaceControl = null; - app.mHasSurface = false; - } + final Rect frame = app.getFrame(); + frame.set(10, 20, 60, 80); + app.updateSurfacePosition(t); + assertTrue(app.mLastSurfacePosition.equals(frame.left, frame.top)); + app.seamlesslyRotateIfAllowed(t, ROTATION_0, ROTATION_90, true /* requested */); + assertTrue(app.mSeamlesslyRotated); + + // Verify we un-rotate the window state surface. + final Matrix matrix = new Matrix(); + // Un-rotate 90 deg. + matrix.setRotate(270); + // Translate it back to origin. + matrix.postTranslate(0, mDisplayInfo.logicalWidth); + verify(t).setMatrix(eq(app.mSurfaceControl), eq(matrix), any(float[].class)); + + // Verify we update the position as well. + final float[] curSurfacePos = {app.mLastSurfacePosition.x, app.mLastSurfacePosition.y}; + matrix.mapPoints(curSurfacePos); + verify(t).setPosition(eq(app.mSurfaceControl), eq(curSurfacePos[0]), eq(curSurfacePos[1])); + + app.finishSeamlessRotation(false /* timeout */); + assertFalse(app.mSeamlesslyRotated); + assertNull(app.mPendingSeamlessRotate); + + // Simulate the case with deferred layout and animation. + app.resetSurfacePositionForAnimationLeash(t); + clearInvocations(t); + mWm.mWindowPlacerLocked.deferLayout(); + app.updateSurfacePosition(t); + // Because layout is deferred, the position should keep the reset value. + assertTrue(app.mLastSurfacePosition.equals(0, 0)); + + app.seamlesslyRotateIfAllowed(t, ROTATION_0, ROTATION_270, true /* requested */); + // The last position must be updated so the surface can be unrotated properly. + assertTrue(app.mLastSurfacePosition.equals(frame.left, frame.top)); + matrix.setRotate(90); + matrix.postTranslate(mDisplayInfo.logicalHeight, 0); + curSurfacePos[0] = frame.left; + curSurfacePos[1] = frame.top; + matrix.mapPoints(curSurfacePos); + verify(t).setPosition(eq(app.mSurfaceControl), eq(curSurfacePos[0]), eq(curSurfacePos[1])); } @Test diff --git a/services/voiceinteraction/OWNERS b/services/voiceinteraction/OWNERS new file mode 100644 index 000000000000..ef1061b28b63 --- /dev/null +++ b/services/voiceinteraction/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/voice/OWNERS diff --git a/services/wifi/OWNERS b/services/wifi/OWNERS new file mode 100644 index 000000000000..2ae7065211d4 --- /dev/null +++ b/services/wifi/OWNERS @@ -0,0 +1 @@ +include /wifi/OWNERS diff --git a/startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java b/startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java index b77c03c1584a..2e7bafe7bdbf 100644 --- a/startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java +++ b/startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java @@ -36,15 +36,15 @@ import java.lang.annotation.RetentionPolicy; */ public class SystemServiceUserEvent implements Parcelable { - /** @see com.android.server.SystemService#onStartUser */ + /** @see com.android.server.SystemService#onUserStarting */ public static final int TYPE_START_USER = 0; - /** @see com.android.server.SystemService#onUnlockUser */ + /** @see com.android.server.SystemService#onUserUnlocking */ public static final int TYPE_UNLOCK_USER = 1; - /** @see com.android.server.SystemService#onSwitchUser*/ + /** @see com.android.server.SystemService#onUserSwitching*/ public static final int TYPE_SWITCH_USER = 2; - /** @see com.android.server.SystemService#onStopUser */ + /** @see com.android.server.SystemService#onUserStopping */ public static final int TYPE_STOP_USER = 3; - /** @see com.android.server.SystemService#onCleanupUser */ + /** @see com.android.server.SystemService#onUserStopped */ public static final int TYPE_CLEANUP_USER = 4; private static final int TYPE_MAX = TYPE_CLEANUP_USER; diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 6288bc1698e9..b1ccb533e83d 100755 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -1988,8 +1988,10 @@ public abstract class ConnectionService extends Service { connection.setAudioModeIsVoip(true); } connection.setTelecomCallId(callId); + PhoneAccountHandle phoneAccountHandle = connection.getPhoneAccountHandle() == null + ? request.getAccountHandle() : connection.getPhoneAccountHandle(); if (connection.getState() != Connection.STATE_DISCONNECTED) { - addConnection(request.getAccountHandle(), callId, connection); + addConnection(phoneAccountHandle, callId, connection); } Uri address = connection.getAddress(); @@ -2005,7 +2007,7 @@ public abstract class ConnectionService extends Service { callId, request, new ParcelableConnection( - request.getAccountHandle(), + phoneAccountHandle, connection.getState(), connection.getConnectionCapabilities(), connection.getConnectionProperties(), diff --git a/telecomm/java/android/telecom/OWNERS b/telecomm/java/android/telecom/OWNERS new file mode 100644 index 000000000000..6656a01403b8 --- /dev/null +++ b/telecomm/java/android/telecom/OWNERS @@ -0,0 +1,6 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +breadley@google.com +hallliu@google.com diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java index 0c463949b14a..4bb7cc47d702 100644 --- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java +++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java @@ -244,7 +244,9 @@ public final class TelephonyPermissions { * <ul> * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling * package passes a DevicePolicyManager Device Owner / Profile Owner device identifier - * access check, or the calling package has carrier privileges on any active subscription. + * access check, or the calling package has carrier privileges on any active + * subscription, or the calling package has the {@link + * Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} appop permission. * <li>throw SecurityException: if the caller does not meet any of the requirements and is * targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission * or carrier privileges of any active subscription. @@ -256,6 +258,10 @@ public final class TelephonyPermissions { */ public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId, String callingPackage, @Nullable String callingFeatureId, String message) { + if (checkCallingOrSelfUseIccAuthWithDeviceIdentifier(context, callingPackage, + callingFeatureId, message)) { + return true; + } return checkPrivilegedReadPermissionOrCarrierPrivilegePermission( context, subId, callingPackage, callingFeatureId, message, true); } @@ -267,7 +273,9 @@ public final class TelephonyPermissions { * <ul> * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling * package passes a DevicePolicyManager Device Owner / Profile Owner device identifier - * access check, or the calling package has carrier privileges on specified subscription. + * access check, or the calling package has carrier privileges on specified subscription, + * or the calling package has the {@link + * Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} appop permission. * <li>throw SecurityException: if the caller does not meet any of the requirements and is * targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission. * <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE @@ -278,6 +286,10 @@ public final class TelephonyPermissions { */ public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId, String callingPackage, @Nullable String callingFeatureId, String message) { + if (checkCallingOrSelfUseIccAuthWithDeviceIdentifier(context, callingPackage, + callingFeatureId, message)) { + return true; + } return checkPrivilegedReadPermissionOrCarrierPrivilegePermission( context, subId, callingPackage, callingFeatureId, message, false); } @@ -385,6 +397,26 @@ public final class TelephonyPermissions { } /** + * Check whether the caller (or self, if not processing an IPC) has {@link + * Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} AppOp permission. + * + * <p>With the permission, the caller can access device/subscriber identifiers and use ICC + * authentication like EAP-AKA. + */ + public static boolean checkCallingOrSelfUseIccAuthWithDeviceIdentifier(Context context, + String callingPackage, String callingFeatureId, String message) { + // Cannot perform appop check if the calling package is null + if (callingPackage == null) { + return false; + } + int callingUid = Binder.getCallingUid(); + AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + int opMode = appOps.noteOpNoThrow(AppOpsManager.OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, + callingUid, callingPackage, callingFeatureId, message); + return opMode == AppOpsManager.MODE_ALLOWED; + } + + /** * Check whether the app with the given pid/uid can read the call log. * @return {@code true} if the specified app has the read call log permission and AppOpp granted * to it, {@code false} otherwise. diff --git a/telephony/java/android/service/euicc/OWNERS b/telephony/java/android/service/euicc/OWNERS new file mode 100644 index 000000000000..6aa399d9ebfb --- /dev/null +++ b/telephony/java/android/service/euicc/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +amitmahajan@google.com diff --git a/telephony/java/android/service/sms/OWNERS b/telephony/java/android/service/sms/OWNERS new file mode 100644 index 000000000000..6aa399d9ebfb --- /dev/null +++ b/telephony/java/android/service/sms/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +amitmahajan@google.com diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java index f900c387f060..99f2e5ee0755 100644 --- a/telephony/java/android/telephony/Annotation.java +++ b/telephony/java/android/telephony/Annotation.java @@ -624,6 +624,20 @@ public class Annotation { public @interface UiccAppType{} /** + * UICC SIM Application Types including UNKNOWN + */ + @IntDef(prefix = { "APPTYPE_" }, value = { + TelephonyManager.APPTYPE_UNKNOWN, + TelephonyManager.APPTYPE_SIM, + TelephonyManager.APPTYPE_USIM, + TelephonyManager.APPTYPE_RUIM, + TelephonyManager.APPTYPE_CSIM, + TelephonyManager.APPTYPE_ISIM + }) + @Retention(RetentionPolicy.SOURCE) + public @interface UiccAppTypeExt{} + + /** * Override network type */ @Retention(RetentionPolicy.SOURCE) diff --git a/apex/statsd/aidl/android/os/IPullAtomCallback.aidl b/telephony/java/android/telephony/IBootstrapAuthenticationCallback.aidl index ff0b97bb5b84..d39ad0e9a2ef 100644 --- a/apex/statsd/aidl/android/os/IPullAtomCallback.aidl +++ b/telephony/java/android/telephony/IBootstrapAuthenticationCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,18 +14,14 @@ * limitations under the License. */ -package android.os; - -import android.os.IPullAtomResultReceiver; +package android.telephony; /** - * Binder interface to pull atoms for the stats service. - * {@hide} - */ -interface IPullAtomCallback { - /** - * Initiate a request for a pull for an atom. - */ - oneway void onPullAtom(int atomTag, IPullAtomResultReceiver resultReceiver); - + * Callback to handle the response of bootstrapAuthenticationRequest + * @hide + */ +oneway interface IBootstrapAuthenticationCallback +{ + void onKeysAvailable(int token, in byte[] gbaKey, String btId); + void onAuthenticationFailure(int token, int reason); } diff --git a/telephony/java/android/telephony/OWNERS b/telephony/java/android/telephony/OWNERS new file mode 100644 index 000000000000..6aa399d9ebfb --- /dev/null +++ b/telephony/java/android/telephony/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +amitmahajan@google.com diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 239329cb447e..b48df717e56c 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -80,12 +80,14 @@ import android.telephony.Annotation.RadioPowerState; import android.telephony.Annotation.SimActivationState; import android.telephony.Annotation.ThermalMitigationResult; import android.telephony.Annotation.UiccAppType; +import android.telephony.Annotation.UiccAppTypeExt; import android.telephony.CallForwardingInfo.CallForwardingReason; import android.telephony.VisualVoicemailService.VisualVoicemailTask; import android.telephony.data.ApnSetting; import android.telephony.data.ApnSetting.MvnoType; import android.telephony.emergency.EmergencyNumber; import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories; +import android.telephony.gba.UaSecurityProtocolIdentifier; import android.telephony.ims.ImsMmTelManager; import android.telephony.ims.aidl.IImsConfig; import android.telephony.ims.aidl.IImsRegistration; @@ -2009,6 +2011,8 @@ public class TelephonyManager { * active subscription. * <li>If the calling app is the default SMS role holder (see {@link * RoleManager#isRoleHeld(String)}). + * <li>If the calling app has been granted the + * {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} permission. * </ul> * * <p>If the calling app does not meet one of these requirements then this method will behave @@ -4019,6 +4023,8 @@ public class TelephonyManager { * <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). * <li>If the calling app is the default SMS role holder (see {@link * RoleManager#isRoleHeld(String)}). + * <li>If the calling app has been granted the + * {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} permission. * </ul> * * <p>If the calling app does not meet one of these requirements then this method will behave @@ -4043,33 +4049,8 @@ public class TelephonyManager { * for a subscription. * Return null if it is unavailable. * - * <p>Starting with API level 29, persistent device identifiers are guarded behind additional - * restrictions, and apps are recommended to use resettable identifiers (see <a - * href="/training/articles/user-data-ids">Best practices for unique identifiers</a>). This - * method can be invoked if one of the following requirements is met: - * <ul> - * <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this - * is a privileged permission that can only be granted to apps preloaded on the device. - * <li>If the calling app is the device or profile owner and has been granted the - * {@link Manifest.permission#READ_PHONE_STATE} permission. The profile owner is an app that - * owns a managed profile on the device; for more details see <a - * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. - * Profile owner access is deprecated and will be removed in a future release. - * <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). - * <li>If the calling app is the default SMS role holder (see {@link - * RoleManager#isRoleHeld(String)}). - * </ul> - * - * <p>If the calling app does not meet one of these requirements then this method will behave - * as follows: - * - * <ul> - * <li>If the calling app's target SDK is API level 28 or lower and the app has the - * READ_PHONE_STATE permission then null is returned.</li> - * <li>If the calling app's target SDK is API level 28 or lower and the app does not have - * the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or - * higher, then a SecurityException is thrown.</li> - * </ul> + * See {@link #getSubscriberId()} for details on the required permissions and behavior + * when the caller does not hold sufficient permissions. * * @param subId whose subscriber id is returned * @hide @@ -5594,57 +5575,6 @@ public class TelephonyManager { } } - /** - * Registers a listener object to receive notification of changes - * in specified telephony states. - * <p> - * To register a listener, pass a {@link PhoneStateListener} and specify at least one telephony - * state of interest in the events argument. - * - * At registration, and when a specified telephony state changes, the telephony manager invokes - * the appropriate callback method on the listener object and passes the current (updated) - * values. - * <p> - * To un-register a listener, pass the listener object and set the events argument to - * {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0). - * - * If this TelephonyManager object has been created with {@link #createForSubscriptionId}, - * applies to the given subId. Otherwise, applies to - * {@link SubscriptionManager#getDefaultSubscriptionId()}. To listen events for multiple subIds, - * pass a separate listener object to each TelephonyManager object created with - * {@link #createForSubscriptionId}. - * - * Note: if you call this method while in the middle of a binder transaction, you <b>must</b> - * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A - * {@link SecurityException} will be thrown otherwise. - * - * This API should be used sparingly -- large numbers of listeners will cause system - * instability. If a process has registered too many listeners without unregistering them, it - * may encounter an {@link IllegalStateException} when trying to register more listeners. - * - * @param events The telephony state(s) of interest to the listener, - * as a bitwise-OR combination of {@link PhoneStateListener} - * LISTEN_ flags. - * @param listener The {@link PhoneStateListener} object to register - * (or unregister) - * @deprecated Use {@link #registerPhoneStateListener(Executor, PhoneStateListener)}. - */ - @Deprecated - public void listen(long events, @NonNull PhoneStateListener listener) { - mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class); - if (mTelephonyRegistryMgr != null) { - if (events != PhoneStateListener.LISTEN_NONE) { - mTelephonyRegistryMgr.registerPhoneStateListenerWithEvents(mSubId, - getOpPackageName(), getAttributionTag(), listener, - Long.valueOf(events).intValue(), getITelephony() != null); - } else { - unregisterPhoneStateListener(listener); - } - } else { - throw new IllegalStateException("telephony service is null."); - } - } - /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"ERI_"}, value = { @@ -7204,6 +7134,8 @@ public class TelephonyManager { } } + /** UICC application type is unknown or not specified */ + public static final int APPTYPE_UNKNOWN = PhoneConstants.APPTYPE_UNKNOWN; /** UICC application type is SIM */ public static final int APPTYPE_SIM = PhoneConstants.APPTYPE_SIM; /** UICC application type is USIM */ @@ -7226,8 +7158,13 @@ public class TelephonyManager { * Returns the response of authentication for the default subscription. * Returns null if the authentication hasn't been successful * - * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE or that the calling - * app has carrier privileges (see {@link #hasCarrierPrivileges}). + * <p>Requires one of the following permissions: + * <ul> + * <li>READ_PRIVILEGED_PHONE_STATE + * <li>the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). + * <li>the calling app has been granted the + * {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} permission. + * </ul> * * @param appType the icc application type, like {@link #APPTYPE_USIM} * @param authType the authentication type, {@link #AUTHTYPE_EAP_AKA} or @@ -7252,7 +7189,8 @@ public class TelephonyManager { * Returns the response of USIM Authentication for specified subId. * Returns null if the authentication hasn't been successful * - * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). + * <p>See {@link #getIccAuthentication(int, int, String)} for details on the required + * permissions. * * @param subId subscription ID used for authentication * @param appType the icc application type, like {@link #APPTYPE_USIM} @@ -7275,7 +7213,8 @@ public class TelephonyManager { IPhoneSubInfo info = getSubscriberInfoService(); if (info == null) return null; - return info.getIccSimChallengeResponse(subId, appType, authType, data); + return info.getIccSimChallengeResponse(subId, appType, authType, data, + getOpPackageName(), getAttributionTag()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { @@ -10023,6 +9962,16 @@ public class TelephonyManager { */ public static final int CARD_POWER_UP_PASS_THROUGH = 2; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"CARD_POWER"}, + value = { + CARD_POWER_DOWN, + CARD_POWER_UP, + CARD_POWER_UP_PASS_THROUGH, + }) + public @interface SimPowerState {} + /** * Set SIM card power state. * @@ -10033,12 +9982,17 @@ public class TelephonyManager { * Callers should monitor for {@link TelephonyIntents#ACTION_SIM_STATE_CHANGED} * broadcasts to determine success or failure and timeout if needed. * + * @deprecated prefer {@link setSimPowerState(int, Executor, Consumer<Integer>)}. + * There is no guarantee that SIM power changes will trigger ACTION_SIM_STATE_CHANGED on new + * devices. + * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} * * {@hide} **/ @SystemApi + @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int state) { setSimPowerStateForSlot(getSlotIndex(), state); @@ -10055,12 +10009,16 @@ public class TelephonyManager { * Callers should monitor for {@link TelephonyIntents#ACTION_SIM_STATE_CHANGED} * broadcasts to determine success or failure and timeout if needed. * + * @deprecated prefer {@link setSimPowerStateForSlot(int, int, Executor, Consumer<Integer>)}. + * changes will trigger ACTION_SIM_STATE_CHANGED on new devices. + * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} * * {@hide} **/ @SystemApi + @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int slotIndex, int state) { try { @@ -10076,6 +10034,85 @@ public class TelephonyManager { } /** + * Set SIM card power state. + * + * @param state State of SIM (power down, power up, pass through) + * @see #CARD_POWER_DOWN + * @see #CARD_POWER_UP + * @see #CARD_POWER_UP_PASS_THROUGH + * @param executor The executor of where the callback will execute. + * @param callback Callback will be triggered once it succeeds or failed. + * @see #SET_SIM_POWER_STATE_SUCCESS + * @see #SET_SIM_POWER_STATE_ALREADY_IN_STATE + * @see #SET_SIM_POWER_STATE_MODEM_ERROR + * @see #SET_SIM_POWER_STATE_SIM_ERROR + * @see #SET_SIM_POWER_STATE_NOT_SUPPORTED + * @throws IllegalArgumentException if requested SIM state is invalid + * + * <p>Requires Permission: + * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} + * + * {@hide} + **/ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public void setSimPowerState(@SimPowerState int state, @NonNull Executor executor, + @NonNull @SetSimPowerStateResult Consumer<Integer> callback) { + setSimPowerStateForSlot(getSlotIndex(), state, executor, callback); + } + + /** + * Set SIM card power state. + * + * @param slotIndex SIM slot id + * @param state State of SIM (power down, power up, pass through) + * @see #CARD_POWER_DOWN + * @see #CARD_POWER_UP + * @see #CARD_POWER_UP_PASS_THROUGH + * @param executor The executor of where the callback will execute. + * @param callback Callback will be triggered once it succeeds or failed. + * @see #SET_SIM_POWER_STATE_SUCCESS + * @see #SET_SIM_POWER_STATE_ALREADY_IN_STATE + * @see #SET_SIM_POWER_STATE_MODEM_ERROR + * @see #SET_SIM_POWER_STATE_SIM_ERROR + * @see #SET_SIM_POWER_STATE_NOT_SUPPORTED + * @throws IllegalArgumentException if requested SIM state is invalid + * + * <p>Requires Permission: + * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} + * + * {@hide} + **/ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public void setSimPowerStateForSlot(int slotIndex, @SimPowerState int state, + @NonNull Executor executor, + @NonNull @SetSimPowerStateResult Consumer<Integer> callback) { + if (state != CARD_POWER_DOWN && state != CARD_POWER_UP + && state != CARD_POWER_UP_PASS_THROUGH) { + throw new IllegalArgumentException("requested SIM state is invalid"); + } + try { + ITelephony telephony = getITelephony(); + IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() { + @Override + public void accept(int result) { + executor.execute(() -> + Binder.withCleanCallingIdentity(() -> callback.accept(result))); + } + }; + if (telephony != null) { + telephony.setSimPowerStateForSlotWithCallback(slotIndex, state, internalCallback); + } + } catch (RemoteException e) { + Log.e(TAG, "Error calling ITelephony#setSimPowerStateForSlot", e); + } catch (SecurityException e) { + Log.e(TAG, "Permission error calling ITelephony#setSimPowerStateForSlot", + e); + } + } + + /** * Set baseband version for the default phone. * * @param version baseband version @@ -11194,6 +11231,55 @@ public class TelephonyManager { public @interface SetCarrierRestrictionResult {} /** + * The SIM power state was successfully set. + * @hide + */ + @SystemApi + public static final int SET_SIM_POWER_STATE_SUCCESS = 0; + + /** + * The SIM is already in the requested power state. + * @hide + */ + @SystemApi + public static final int SET_SIM_POWER_STATE_ALREADY_IN_STATE = 1; + + /** + * Failed to connect to the modem to make the power state request. This may happen if the + * modem has an error. The user may want to make the request again later. + * @hide + */ + @SystemApi + public static final int SET_SIM_POWER_STATE_MODEM_ERROR = 2; + + /** + * Failed to connect to the SIM to make the power state request. This may happen if the + * SIM has been removed. The user may want to make the request again later. + * @hide + */ + @SystemApi + public static final int SET_SIM_POWER_STATE_SIM_ERROR = 3; + + /** + * The modem version does not support synchronous power. + * @hide + */ + @SystemApi + public static final int SET_SIM_POWER_STATE_NOT_SUPPORTED = 4; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"SET_SIM_POWER_STATE_"}, + value = { + SET_SIM_POWER_STATE_SUCCESS, + SET_SIM_POWER_STATE_ALREADY_IN_STATE, + SET_SIM_POWER_STATE_MODEM_ERROR, + SET_SIM_POWER_STATE_SIM_ERROR, + SET_SIM_POWER_STATE_NOT_SUPPORTED + }) + public @interface SetSimPowerStateResult {} + + /** * Set the allowed carrier list and the excluded carrier list indicating the priority between * the two lists. * Requires system privileges. @@ -14415,4 +14501,173 @@ public class TelephonyManager { throw new IllegalStateException("telephony service is null."); } } + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"GBA_FAILURE_REASON_"}, value = { + GBA_FAILURE_REASON_UNKNOWN, + GBA_FAILURE_REASON_FEATURE_NOT_SUPPORTED, + GBA_FAILURE_REASON_FEATURE_NOT_READY, + GBA_FAILURE_REASON_NETWORK_FAILURE, + GBA_FAILURE_REASON_INCORRECT_NAF_ID, + GBA_FAILURE_REASON_SECURITY_PROTOCOL_NOT_SUPPORTED}) + public @interface AuthenticationFailureReason {} + + /** + * GBA Authentication has failed for an unknown reason. + * + * <p>The caller should retry a message that failed with this response. + * @hide + */ + @SystemApi + public static final int GBA_FAILURE_REASON_UNKNOWN = 0; + + /** + * GBA Authentication is not supported by the carrier, SIM or android. + * + * <p>Application should use other authentication mechanisms if possible. + * @hide + */ + @SystemApi + public static final int GBA_FAILURE_REASON_FEATURE_NOT_SUPPORTED = 1; + + /** + * GBA Authentication service is not ready for use. + * + * <p>Application could try again at a later time. + * @hide + */ + @SystemApi + public static final int GBA_FAILURE_REASON_FEATURE_NOT_READY = 2; + + /** + * GBA Authentication has been failed by the network. + * @hide + */ + @SystemApi + public static final int GBA_FAILURE_REASON_NETWORK_FAILURE = 3; + + /** + * GBA Authentication has failed due to incorrect NAF URL. + * @hide + */ + @SystemApi + public static final int GBA_FAILURE_REASON_INCORRECT_NAF_ID = 4; + + /** + * GBA Authentication has failed due to unsupported security protocol + * @hide + */ + @SystemApi + public static final int GBA_FAILURE_REASON_SECURITY_PROTOCOL_NOT_SUPPORTED = 5; + + /** + * The callback associated with a {@link #bootstrapAuthenticationRequest()}. + * @hide + */ + @SystemApi + public static class BootstrapAuthenticationCallback { + + /** + * Invoked when the previously requested GBA keys are available (@see + * bootstrapAuthenticationRequest()). + * @param gbaKey Ks_NAF/Ks_ext_NAF Response + * @param transactionId Bootstrapping Transaction Identifier + */ + public void onKeysAvailable(@NonNull byte[] gbaKey, @NonNull String transactionId) {} + + /** + * @param reason The reason for the authentication failure. + */ + public void onAuthenticationFailure(@AuthenticationFailureReason int reason) {} + } + + /** + * Used to get the Generic Bootstrapping Architecture authentication keys + * KsNAF/Ks_ext_NAF for a particular NAF as defined in 3GPP spec TS 33.220 for + * the specified sub id. + * + * <p>Application must be prepared to wait for receiving the Gba keys through the + * registered callback and not invoke the API on the main application thread. + * Application also must call the api to get the fresh key every time instead + * of caching the key. + * + * Following steps may be invoked on the API call depending on the state of the + * underlying GBA implementation: + * <ol> + * <li>Resolve and bind to a Gba implementation.</li> + * <li>Run bootstrapping if no valid keys are available or bootstrapping is forced.</li> + * <li>Generate the ks_NAF/ ks_Ext_NAF to be returned via the callback.</li> + * </ol> + * + * <p> Requires Permission: MODIFY_PHONE_STATE or that the calling app has carrier + * privileges (see {@link #hasCarrierPrivileges}). + * @param appType icc application type, like {@link #APPTYPE_USIM} or {@link + * #APPTYPE_ISIM} or {@link#APPTYPE_UNKNOWN} + * @param nafId Network Application Function(NAF) fully qualified domain name and + * the selected GBA mode. It shall contain two parts delimited by "@" sign. The first + * part is the constant string "3GPP-bootstrapping" (GBA_ME), + * "3GPP-bootstrapping-uicc" (GBA_ U), or "3GPP-bootstrapping-digest" (GBA_Digest), + * and the latter part shall be the FQDN of the NAF (e.g. + * "3GPP-bootstrapping@naf1.operator.com" or "3GPP-bootstrapping-uicc@naf1.operator.com", + * or "3GPP-bootstrapping-digest@naf1.operator.com"). + * @param securityProtocol Security protocol identifier between UE and NAF. See + * 3GPP TS 33.220 Annex H. Application can use + * {@link UaSecurityProtocolIdentifier#createDefaultUaSpId}, + * {@link UaSecurityProtocolIdentifier#create3GppUaSpId}, + * to create the ua security protocol identifier as needed + * @param forceBootStrapping true=force bootstrapping, false=do not force + * bootstrapping. Bootstrapping shouldn't be forced unless the application sees + * authentication errors from the server. + * @param e The {@link Executor} that will be used to call the Gba callback. + * @param callback A callback called on the supplied {@link Executor} that will + * contain the GBA Ks_NAF/Ks_ext_NAF when available. If the NAF keys are + * available and valid at the time of call and bootstrapping is not requested, + * then the callback shall be invoked with the available keys. + * @hide + */ + @SystemApi + @WorkerThread + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public void bootstrapAuthenticationRequest( + @UiccAppTypeExt int appType, @NonNull Uri nafId, + @NonNull UaSecurityProtocolIdentifier securityProtocol, + boolean forceBootStrapping, @NonNull Executor e, + @NonNull BootstrapAuthenticationCallback callback) { + try { + ITelephony service = getITelephony(); + if (service == null) { + e.execute(() -> callback.onAuthenticationFailure( + GBA_FAILURE_REASON_FEATURE_NOT_READY)); + return; + } + service.bootstrapAuthenticationRequest( + getSubId(), appType, nafId, securityProtocol, forceBootStrapping, + new IBootstrapAuthenticationCallback.Stub() { + @Override + public void onKeysAvailable(int token, byte[] gbaKey, + String transactionId) { + final long identity = Binder.clearCallingIdentity(); + try { + e.execute(() -> callback.onKeysAvailable(gbaKey, transactionId)); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void onAuthenticationFailure(int token, int reason) { + final long identity = Binder.clearCallingIdentity(); + try { + e.execute(() -> callback.onAuthenticationFailure(reason)); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + }); + } catch (RemoteException exception) { + Log.e(TAG, "Error calling ITelephony#bootstrapAuthenticationRequest", exception); + e.execute(() -> callback.onAuthenticationFailure(GBA_FAILURE_REASON_FEATURE_NOT_READY)); + } + } } diff --git a/telephony/java/android/telephony/cdma/OWNERS b/telephony/java/android/telephony/cdma/OWNERS new file mode 100644 index 000000000000..6aa399d9ebfb --- /dev/null +++ b/telephony/java/android/telephony/cdma/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +amitmahajan@google.com diff --git a/telephony/java/android/telephony/data/OWNERS b/telephony/java/android/telephony/data/OWNERS new file mode 100644 index 000000000000..932b35cbdff7 --- /dev/null +++ b/telephony/java/android/telephony/data/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +jackyu@google.com diff --git a/telephony/java/android/telephony/emergency/OWNERS b/telephony/java/android/telephony/emergency/OWNERS new file mode 100644 index 000000000000..fa07dce5f615 --- /dev/null +++ b/telephony/java/android/telephony/emergency/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +shuoq@google.com diff --git a/telephony/java/android/telephony/euicc/OWNERS b/telephony/java/android/telephony/euicc/OWNERS new file mode 100644 index 000000000000..9e51a4b30516 --- /dev/null +++ b/telephony/java/android/telephony/euicc/OWNERS @@ -0,0 +1,6 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +refuhoo@google.com +amitmahajan@google.com diff --git a/telephony/java/android/telephony/gba/GbaAuthRequest.aidl b/telephony/java/android/telephony/gba/GbaAuthRequest.aidl new file mode 100644 index 000000000000..ba243a27b4be --- /dev/null +++ b/telephony/java/android/telephony/gba/GbaAuthRequest.aidl @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.telephony.gba; + +parcelable GbaAuthRequest; diff --git a/telephony/java/android/telephony/gba/GbaAuthRequest.java b/telephony/java/android/telephony/gba/GbaAuthRequest.java new file mode 100644 index 000000000000..5366e9af3147 --- /dev/null +++ b/telephony/java/android/telephony/gba/GbaAuthRequest.java @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.gba; + +import android.annotation.NonNull; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; +import android.telephony.IBootstrapAuthenticationCallback; + +import com.android.internal.telephony.uicc.IccUtils; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * GBA authentication request + * {@hide} + */ +public final class GbaAuthRequest implements Parcelable { + private int mToken; + private int mSubId; + private int mAppType; + private Uri mNafUrl; + private byte[] mSecurityProtocol; + private boolean mForceBootStrapping; + private IBootstrapAuthenticationCallback mCallback; + + private static AtomicInteger sUniqueToken = new AtomicInteger(0); + + public GbaAuthRequest(int subId, int appType, Uri nafUrl, byte[] securityProtocol, + boolean forceBootStrapping, IBootstrapAuthenticationCallback callback) { + this(nextUniqueToken(), subId, appType, nafUrl, + securityProtocol, forceBootStrapping, callback); + } + + public GbaAuthRequest(GbaAuthRequest request) { + this(request.mToken, request.mSubId, request.mAppType, request.mNafUrl, + request.mSecurityProtocol, request.mForceBootStrapping, request.mCallback); + } + + public GbaAuthRequest(int token, int subId, int appType, Uri nafUrl, byte[] securityProtocol, + boolean forceBootStrapping, IBootstrapAuthenticationCallback callback) { + mToken = token; + mSubId = subId; + mAppType = appType; + mNafUrl = nafUrl; + mSecurityProtocol = securityProtocol; + mCallback = callback; + mForceBootStrapping = forceBootStrapping; + } + + public int getToken() { + return mToken; + } + + public int getSubId() { + return mSubId; + } + + public int getAppType() { + return mAppType; + } + + public Uri getNafUrl() { + return mNafUrl; + } + + public byte[] getSecurityProtocol() { + return mSecurityProtocol; + } + + public boolean isForceBootStrapping() { + return mForceBootStrapping; + } + + public void setCallback(IBootstrapAuthenticationCallback cb) { + mCallback = cb; + } + + public IBootstrapAuthenticationCallback getCallback() { + return mCallback; + } + + /** + * {@link Parcelable#writeToParcel} + */ + public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeInt(mToken); + out.writeInt(mSubId); + out.writeInt(mAppType); + out.writeParcelable(mNafUrl, 0); + out.writeInt(mSecurityProtocol.length); + out.writeByteArray(mSecurityProtocol); + out.writeBoolean(mForceBootStrapping); + out.writeStrongInterface(mCallback); + } + + /** + * {@link Parcelable.Creator} + * + */ + public static final @android.annotation.NonNull Parcelable.Creator< + GbaAuthRequest> CREATOR = new Creator<GbaAuthRequest>() { + @Override + public GbaAuthRequest createFromParcel(Parcel in) { + int token = in.readInt(); + int subId = in.readInt(); + int appType = in.readInt(); + Uri nafUrl = in.readParcelable(GbaAuthRequest.class.getClassLoader()); + int len = in.readInt(); + byte[] protocol = new byte[len]; + in.readByteArray(protocol); + boolean forceBootStrapping = in.readBoolean(); + IBootstrapAuthenticationCallback callback = + IBootstrapAuthenticationCallback.Stub + .asInterface(in.readStrongBinder()); + return new GbaAuthRequest(token, subId, appType, nafUrl, protocol, + forceBootStrapping, callback); + } + + @Override + public GbaAuthRequest[] newArray(int size) { + return new GbaAuthRequest[size]; + } + }; + + /** + * {@link Parcelable#describeContents} + */ + public int describeContents() { + return 0; + } + + private static int nextUniqueToken() { + return sUniqueToken.getAndIncrement() << 16 | (0xFFFF & (int) System.currentTimeMillis()); + } + + @Override + public String toString() { + String str = "Token: " + mToken + "SubId:" + mSubId + ", AppType:" + + mAppType + ", NafUrl:" + mNafUrl + ", SecurityProtocol:" + + IccUtils.bytesToHexString(mSecurityProtocol) + + ", ForceBootStrapping:" + mForceBootStrapping + + ", CallBack:" + mCallback; + return str; + } +} diff --git a/telephony/java/android/telephony/gba/GbaService.java b/telephony/java/android/telephony/gba/GbaService.java new file mode 100644 index 000000000000..3962aff9df4f --- /dev/null +++ b/telephony/java/android/telephony/gba/GbaService.java @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.gba; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.app.Service; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.telephony.Annotation.UiccAppTypeExt; +import android.telephony.IBootstrapAuthenticationCallback; +import android.telephony.TelephonyManager; +import android.telephony.TelephonyManager.AuthenticationFailureReason; +import android.util.Log; +import android.util.SparseArray; + +/** + * Base class for GBA Service. Any implementation which wants to provide + * GBA service must extend this class. + * + * <p>Note that the application to implement the service must declare to use + * the permission {@link android.Manifest.permission#BIND_GBA_SERVICE}, + * and filter the intent of {@link #SERVICE_INTERFACE}. + * The manifest of the service must follow the format below: + * + * <p>... + * <service + * android:name=".EgGbaService" + * android:directBootAware="true" + * android:permission="android.permission.BIND_GBA_SERVICE" > + * ... + * <intent-filter> + * <action android:name="android.telephony.gba.GbaService"/> + * </intent-filter> + * </service> + * ... + * + * <p>The service should also be file-based encryption (FBE) aware. + * {@hide} + */ +@SystemApi +public class GbaService extends Service { + private static final boolean DBG = Build.IS_DEBUGGABLE; + private static final String TAG = "GbaService"; + + /** + * The intent must be defined as an intent-filter in the + * AndroidManifest of the GbaService. + */ + public static final String SERVICE_INTERFACE = "android.telephony.gba.GbaService"; + + private static final int EVENT_GBA_AUTH_REQUEST = 1; + + private final HandlerThread mHandlerThread; + private final GbaServiceHandler mHandler; + + private final SparseArray<IBootstrapAuthenticationCallback> mCallbacks = new SparseArray<>(); + private final IGbaServiceWrapper mBinder = new IGbaServiceWrapper(); + + /** + * Default constructor. + */ + public GbaService() { + mHandlerThread = new HandlerThread(TAG); + mHandlerThread.start(); + + mHandler = new GbaServiceHandler(mHandlerThread.getLooper()); + Log.d(TAG, "GBA service created"); + } + + private class GbaServiceHandler extends Handler { + + GbaServiceHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case EVENT_GBA_AUTH_REQUEST: + GbaAuthRequest req = (GbaAuthRequest) msg.obj; + synchronized (mCallbacks) { + mCallbacks.put(req.getToken(), req.getCallback()); + } + onAuthenticationRequest(req.getSubId(), req.getToken(), req.getAppType(), + req.getNafUrl(), req.getSecurityProtocol(), req.isForceBootStrapping()); + break; + default: + break; + } + } + } + + /** + * Called by the platform when a GBA authentication request is received from + * {@link TelephonyManager#bootstrapAuthenticationRequest} to get the KsNAF for + * a particular NAF. + * + * @param subscriptionId the ICC card to be used for the bootstrapping authentication. + * @param token the identification of the authentication request. + * @param appType icc application type, like {@link #APPTYPE_USIM} or {@link + * #APPTYPE_ISIM} or {@link#APPTYPE_UNKNOWN} + * @param nafUrl Network Application Function(NAF) fully qualified domain name and + * the selected GBA mode. It shall contain two parts delimited by "@" sign. The first + * part is the constant string "3GPP-bootstrapping" (GBA_ME), + * "3GPP-bootstrapping-uicc" (GBA_ U), or "3GPP-bootstrapping-digest" (GBA_Digest), + * and the latter part shall be the FQDN of the NAF (e.g. + * "3GPP-bootstrapping@naf1.operator.com" or "3GPP-bootstrapping-uicc@naf1.operator.com", + * or "3GPP-bootstrapping-digest@naf1.operator.com"). + * @param securityProtocol Security protocol identifier between UE and NAF. See + * 3GPP TS 33.220 Annex H. Application can use + * {@link UaSecurityProtocolIdentifier#createDefaultUaSpId}, + * {@link UaSecurityProtocolIdentifier#create3GppUaSpId}, + * to create the ua security protocol identifier as needed + * @param forceBootStrapping true=force bootstrapping, false=do not force + * bootstrapping. Bootstrapping shouldn't be forced unless the application sees + * authentication errors from the server. + * Response is returned via {@link TelephonyManager#BootstrapAuthenticationCallback} + * along with the token to identify the request. + * + * <p>Note that this is not called in the main thread. + */ + public void onAuthenticationRequest(int subscriptionId, int token, @UiccAppTypeExt int appType, + @NonNull Uri nafUrl, @NonNull byte[] securityProtocol, boolean forceBootStrapping) { + //Default implementation should be overridden by vendor Gba Service. Vendor Gba Service + //should handle the gba bootstrap authentication request, and call reportKeysAvailable or + //reportAuthenticationFailure to notify the caller accordingly. + reportAuthenticationFailure( + token, TelephonyManager.GBA_FAILURE_REASON_FEATURE_NOT_SUPPORTED); + } + + /** + * Called by {@link GbaService} when the previously requested GBA keys are available + * (@see onAuthenticationRequest()) + * + * @param token unique identifier of the request. + * @param gbaKey KsNaf Response. + * @param transactionId Bootstrapping Transaction ID. + * @throws RuntimeException when there is remote failure of callback. + */ + public final void reportKeysAvailable(int token, @NonNull byte[] gbaKey, + @NonNull String transactionId) throws RuntimeException { + IBootstrapAuthenticationCallback cb = null; + synchronized (mCallbacks) { + cb = mCallbacks.get(token); + mCallbacks.remove(token); + } + if (cb != null) { + try { + cb.onKeysAvailable(token, gbaKey, transactionId); + } catch (RemoteException exception) { + throw exception.rethrowAsRuntimeException(); + } + } + } + + /** + * Invoked when the previously requested GBA key authentication failed + * (@see onAuthenticationRequest()) + * + * @param token unique identifier of the request. + * @param reason The reason for the authentication failure. + * @throws RuntimeException when there is remote failure of callback. + */ + public final void reportAuthenticationFailure(int token, + @AuthenticationFailureReason int reason) throws RuntimeException { + IBootstrapAuthenticationCallback cb = null; + synchronized (mCallbacks) { + cb = mCallbacks.get(token); + mCallbacks.remove(token); + } + if (cb != null) { + try { + cb.onAuthenticationFailure(token, reason); + } catch (RemoteException exception) { + throw exception.rethrowAsRuntimeException(); + } + } + } + + /** @hide */ + @Override + public IBinder onBind(Intent intent) { + if (SERVICE_INTERFACE.equals(intent.getAction())) { + Log.d(TAG, "GbaService Bound."); + return mBinder; + } + return null; + } + + /** @hide */ + @Override + public void onDestroy() { + mHandlerThread.quit(); + super.onDestroy(); + } + + private class IGbaServiceWrapper extends IGbaService.Stub { + @Override + public void authenticationRequest(GbaAuthRequest request) { + if (DBG) Log.d(TAG, "receive request: " + request); + mHandler.obtainMessage(EVENT_GBA_AUTH_REQUEST, request).sendToTarget(); + } + } +} diff --git a/apex/statsd/aidl/android/os/IPullAtomResultReceiver.aidl b/telephony/java/android/telephony/gba/IGbaService.aidl index 00d026e25df3..b7ba5a4441ec 100644 --- a/apex/statsd/aidl/android/os/IPullAtomResultReceiver.aidl +++ b/telephony/java/android/telephony/gba/IGbaService.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,20 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package android.telephony.gba; -package android.os; - -import android.util.StatsEventParcel; +import android.net.Uri; +import android.telephony.gba.GbaAuthRequest; /** - * Binder interface to pull atoms for the stats service. - * {@hide} - */ -interface IPullAtomResultReceiver { - - /** - * Indicate that a pull request for an atom is complete. - */ - oneway void pullFinished(int atomTag, boolean success, in StatsEventParcel[] output); - + * @hide + */ +interface IGbaService +{ + oneway void authenticationRequest(in GbaAuthRequest request); } diff --git a/telephony/java/android/telephony/gba/TlsParams.java b/telephony/java/android/telephony/gba/TlsParams.java new file mode 100644 index 000000000000..922f4bbb4dbf --- /dev/null +++ b/telephony/java/android/telephony/gba/TlsParams.java @@ -0,0 +1,281 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.telephony.gba; + +import android.annotation.IntDef; +import android.annotation.SystemApi; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; + +/** + * Defines the TLS parameters for GBA as per IANA and TS 33.210, which are used + * by some UA security protocol identifiers defined in 3GPP TS 33.220 Annex H, + * and 3GPP TS 33.222. + * + * @hide + */ +@SystemApi +public class TlsParams { + + private TlsParams() {} + + /** + * TLS protocol version supported by GBA + */ + public static final int PROTOCOL_VERSION_TLS_1_2 = 0x0303; + public static final int PROTOCOL_VERSION_TLS_1_3 = 0x0304; + + /** + * TLS cipher suites are used to create {@link UaSecurityProtocolIdentifier} + * by {@link UaSecurityProtocolIdentifier#create3GppUaSpId} + * + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef( + prefix = {"TLS_"}, + value = { + TLS_NULL_WITH_NULL_NULL, + TLS_RSA_WITH_NULL_MD5, + TLS_RSA_WITH_NULL_SHA, + TLS_RSA_WITH_RC4_128_MD5, + TLS_RSA_WITH_RC4_128_SHA, + TLS_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA, + TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, + TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_DH_ANON_WITH_RC4_128_MD5, + TLS_DH_ANON_WITH_3DES_EDE_CBC_SHA, + TLS_RSA_WITH_AES_128_CBC_SHA, + TLS_DH_DSS_WITH_AES_128_CBC_SHA, + TLS_DH_RSA_WITH_AES_128_CBC_SHA, + TLS_DHE_DSS_WITH_AES_128_CBC_SHA, + TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + TLS_DH_ANON_WITH_AES_128_CBC_SHA, + TLS_RSA_WITH_AES_256_CBC_SHA, + TLS_DH_DSS_WITH_AES_256_CBC_SHA, + TLS_DH_RSA_WITH_AES_256_CBC_SHA, + TLS_DHE_DSS_WITH_AES_256_CBC_SHA, + TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + TLS_DH_ANON_WITH_AES_256_CBC_SHA, + TLS_RSA_WITH_NULL_SHA256, + TLS_RSA_WITH_AES_128_CBC_SHA256, + TLS_RSA_WITH_AES_256_CBC_SHA256, + TLS_DH_DSS_WITH_AES_128_CBC_SHA256, + TLS_DH_RSA_WITH_AES_128_CBC_SHA256, + TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, + TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_DH_DSS_WITH_AES_256_CBC_SHA256, + TLS_DH_RSA_WITH_AES_256_CBC_SHA256, + TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + TLS_DH_ANON_WITH_AES_128_CBC_SHA256, + TLS_DH_ANON_WITH_AES_256_CBC_SHA256, + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, + TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, + TLS_AES_128_GCM_SHA256, + TLS_AES_256_GCM_SHA384, + TLS_CHACHA20_POLY1305_SHA256, + TLS_AES_128_CCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_DHE_RSA_WITH_AES_128_CCM, + TLS_DHE_RSA_WITH_AES_256_CCM, + TLS_DHE_PSK_WITH_AES_128_CCM, + TLS_DHE_PSK_WITH_AES_256_CCM, + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256 + }) + public @interface TlsCipherSuite {} + + // Cipher suites for TLS v1.2 per RFC5246 + public static final int TLS_NULL_WITH_NULL_NULL = 0x0000; + public static final int TLS_RSA_WITH_NULL_MD5 = 0x0001; + public static final int TLS_RSA_WITH_NULL_SHA = 0x0002; + public static final int TLS_RSA_WITH_RC4_128_MD5 = 0x0004; + public static final int TLS_RSA_WITH_RC4_128_SHA = 0x0005; + public static final int TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A; + public static final int TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D; + public static final int TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010; + public static final int TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013; + public static final int TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016; + public static final int TLS_DH_ANON_WITH_RC4_128_MD5 = 0x0018; + public static final int TLS_DH_ANON_WITH_3DES_EDE_CBC_SHA = 0x001B; + public static final int TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F; + public static final int TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030; + public static final int TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031; + public static final int TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032; + public static final int TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033; + public static final int TLS_DH_ANON_WITH_AES_128_CBC_SHA = 0x0034; + public static final int TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035; + public static final int TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036; + public static final int TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037; + public static final int TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038; + public static final int TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039; + public static final int TLS_DH_ANON_WITH_AES_256_CBC_SHA = 0x003A; + public static final int TLS_RSA_WITH_NULL_SHA256 = 0x003B; + public static final int TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C; + public static final int TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D; + public static final int TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x003E; + public static final int TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x003F; + public static final int TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040; + public static final int TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067; + public static final int TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x0068; + public static final int TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x0069; + public static final int TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A; + public static final int TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B; + public static final int TLS_DH_ANON_WITH_AES_128_CBC_SHA256 = 0x006C; + public static final int TLS_DH_ANON_WITH_AES_256_CBC_SHA256 = 0x006D; + + // Cipher suites for TLS v1.3 per RFC8446 and recommended by IANA + public static final int TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E; + public static final int TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F; + public static final int TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 0x00AA; + public static final int TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 0x00AB; + public static final int TLS_AES_128_GCM_SHA256 = 0x1301; + public static final int TLS_AES_256_GCM_SHA384 = 0x1302; + public static final int TLS_CHACHA20_POLY1305_SHA256 = 0x1303; + public static final int TLS_AES_128_CCM_SHA256 = 0x1304; + public static final int TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B; + public static final int TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C; + public static final int TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F; + public static final int TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030; + public static final int TLS_DHE_RSA_WITH_AES_128_CCM = 0xC09E; + public static final int TLS_DHE_RSA_WITH_AES_256_CCM = 0xC09F; + public static final int TLS_DHE_PSK_WITH_AES_128_CCM = 0xC0A6; + public static final int TLS_DHE_PSK_WITH_AES_256_CCM = 0xC0A7; + public static final int TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA8; + public static final int TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA9; + public static final int TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAA; + public static final int TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAC; + public static final int TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAD; + public static final int TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 = 0xD001; + public static final int TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384 = 0xD002; + public static final int TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256 = 0xD005; + + private static final int[] CS_EXPECTED = { + TLS_NULL_WITH_NULL_NULL, + TLS_RSA_WITH_NULL_MD5, + TLS_RSA_WITH_NULL_SHA, + TLS_RSA_WITH_RC4_128_MD5, + TLS_RSA_WITH_RC4_128_SHA, + TLS_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA, + TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, + TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_DH_ANON_WITH_RC4_128_MD5, + TLS_DH_ANON_WITH_3DES_EDE_CBC_SHA, + TLS_RSA_WITH_AES_128_CBC_SHA, + TLS_DH_DSS_WITH_AES_128_CBC_SHA, + TLS_DH_RSA_WITH_AES_128_CBC_SHA, + TLS_DHE_DSS_WITH_AES_128_CBC_SHA, + TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + TLS_DH_ANON_WITH_AES_128_CBC_SHA, + TLS_RSA_WITH_AES_256_CBC_SHA, + TLS_DH_DSS_WITH_AES_256_CBC_SHA, + TLS_DH_RSA_WITH_AES_256_CBC_SHA, + TLS_DHE_DSS_WITH_AES_256_CBC_SHA, + TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + TLS_DH_ANON_WITH_AES_256_CBC_SHA, + TLS_RSA_WITH_NULL_SHA256, + TLS_RSA_WITH_AES_128_CBC_SHA256, + TLS_RSA_WITH_AES_256_CBC_SHA256, + TLS_DH_DSS_WITH_AES_128_CBC_SHA256, + TLS_DH_RSA_WITH_AES_128_CBC_SHA256, + TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, + TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_DH_DSS_WITH_AES_256_CBC_SHA256, + TLS_DH_RSA_WITH_AES_256_CBC_SHA256, + TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + TLS_DH_ANON_WITH_AES_128_CBC_SHA256, + TLS_DH_ANON_WITH_AES_256_CBC_SHA256, + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, + TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, + TLS_AES_128_GCM_SHA256, + TLS_AES_256_GCM_SHA384, + TLS_CHACHA20_POLY1305_SHA256, + TLS_AES_128_CCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_DHE_RSA_WITH_AES_128_CCM, + TLS_DHE_RSA_WITH_AES_256_CCM, + TLS_DHE_PSK_WITH_AES_128_CCM, + TLS_DHE_PSK_WITH_AES_256_CCM, + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256 + }; + + /** + * TLS supported groups required by TS 33.210 + */ + public static final int GROUP_SECP256R1 = 23; + public static final int GROUP_SECP384R1 = 24; + public static final int GROUP_X25519 = 29; + public static final int GROUP_X448 = 30; + + /** + * Signature algorithms shall be supported as per TS 33.210 + */ + public static final int SIG_RSA_PKCS1_SHA1 = 0X0201; + public static final int SIG_ECDSA_SHA1 = 0X0203; + public static final int SIG_RSA_PKCS1_SHA256 = 0X0401; + public static final int SIG_ECDSA_SECP256R1_SHA256 = 0X0403; + public static final int SIG_RSA_PKCS1_SHA256_LEGACY = 0X0420; + public static final int SIG_RSA_PKCS1_SHA384 = 0X0501; + public static final int SIG_ECDSA_SECP384R1_SHA384 = 0X0503; + public static final int SIG_RSA_PKCS1_SHA384_LEGACY = 0X0520; + public static final int SIG_RSA_PKCS1_SHA512 = 0X0601; + public static final int SIG_ECDSA_SECP521R1_SHA512 = 0X0603; + public static final int SIG_RSA_PKCS1_SHA512_LEGACY = 0X0620; + public static final int SIG_RSA_PSS_RSAE_SHA256 = 0X0804; + public static final int SIG_RSA_PSS_RSAE_SHA384 = 0X0805; + public static final int SIG_RSA_PSS_RSAE_SHA512 = 0X0806; + public static final int SIG_ECDSA_BRAINPOOLP256R1TLS13_SHA256 = 0X081A; + public static final int SIG_ECDSA_BRAINPOOLP384R1TLS13_SHA384 = 0X081B; + public static final int SIG_ECDSA_BRAINPOOLP512R1TLS13_SHA512 = 0X081C; + + /** + * Returns whether the TLS cipher suite id is supported + */ + public static boolean isTlsCipherSuiteSupported(int csId) { + return Arrays.binarySearch(CS_EXPECTED, csId) >= 0; + } +} diff --git a/telephony/java/android/telephony/gba/UaSecurityProtocolIdentifier.aidl b/telephony/java/android/telephony/gba/UaSecurityProtocolIdentifier.aidl new file mode 100644 index 000000000000..a71e860fd54c --- /dev/null +++ b/telephony/java/android/telephony/gba/UaSecurityProtocolIdentifier.aidl @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.telephony.gba; + +parcelable UaSecurityProtocolIdentifier; diff --git a/telephony/java/android/telephony/gba/UaSecurityProtocolIdentifier.java b/telephony/java/android/telephony/gba/UaSecurityProtocolIdentifier.java new file mode 100644 index 000000000000..c1418758f64f --- /dev/null +++ b/telephony/java/android/telephony/gba/UaSecurityProtocolIdentifier.java @@ -0,0 +1,436 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.telephony.gba; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.telephony.gba.TlsParams.TlsCipherSuite; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.nio.ByteBuffer; +import java.util.Objects; + +/** + * Description of ua security protocol identifier defined in 3GPP TS 33.220 H.2 + * @hide + */ +@SystemApi +public final class UaSecurityProtocolIdentifier implements Parcelable { + + /** + * Organization code defined in 3GPP TS 33.220 H.3 + * + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"ORG_"}, value = { + ORG_NONE, + ORG_3GPP, + ORG_3GPP2, + ORG_OMA, + ORG_GSMA, + ORG_LOCAL}) + public @interface OrganizationCode {} + + /** + * Organization octet value for default ua security protocol + */ + public static final int ORG_NONE = 0; + /** + * Organization octet value for 3GPP ua security protocol + */ + public static final int ORG_3GPP = 0x01; + /** + * Organization octet value for 3GPP2 ua security protocol + */ + public static final int ORG_3GPP2 = 0x02; + /** + * Organization octet value for OMA ua security protocol + */ + public static final int ORG_OMA = 0x03; + /** + * Organization octet value for GSMA ua security protocol + */ + public static final int ORG_GSMA = 0x04; + /** + * Internal organization octet value for local/experimental protocols + */ + public static final int ORG_LOCAL = 0xFF; + + /** + * 3GPP UA Security Protocol ID defined in 3GPP TS 33.220 H.3 + * + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"UA_SECURITY_PROTOCOL_3GPP_"}, value = { + UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE, + UA_SECURITY_PROTOCOL_3GPP_MBMS, + UA_SECURITY_PROTOCOL_3GPP_HTTP_DIGEST_AUTHENTICATION, + UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS, + UA_SECURITY_PROTOCOL_3GPP_SIP_BASED_MBMS, + UA_SECURITY_PROTOCOL_3GPP_GENERIC_PUSH_LAYER, + UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE, + UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI, + UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT, + UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER}) + public @interface UaSecurityProtocol3gpp {} + + /** + * Security protocol param according to TS 33.221 as described in TS + * 33.220 Annex H. Mapped to byte stream "0x01,0x00,0x00,0x00,0x00". + */ + public static final int UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE = 0; + + /** + * Security protocol param according to TS 33.246 for Multimedia + * broadcast/Multimedia services (MBMS) as described in TS + * 33.220 Annex H. Mapped to byte stream "0x01,0x00,0x00,0x00,0x01". + */ + public static final int UA_SECURITY_PROTOCOL_3GPP_MBMS = 1; + + /** + * Security protocol param based on HTTP digest authentication + * according to TS 24.109 as described in TS 33.220 Annex H. Mapped to + * byte stream "0x01,0x00,0x00,0x00,0x02". + */ + public static final int UA_SECURITY_PROTOCOL_3GPP_HTTP_DIGEST_AUTHENTICATION = 2; + + /** + * Security protocol param used with HTTP-based security procedures for + * Multimedia broadcast/Multimedia services (MBMS) user services + * according to TS 26.237 as described in TS 33.220 Annex H. + * Mapped to byte stream "0x01,0x00,0x00,0x00,0x03". + */ + public static final int UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS = 3; + + /** + * Security protocol param used with SIP-based security procedures for + * Multimedia broadcast/Multimedia services (MBMS) user services + * according to TS 26.237 as described in TS 33.220 Annex H. + * Mapped to byte stream "0x01,0x00,0x00,0x00,0x04". + */ + public static final int UA_SECURITY_PROTOCOL_3GPP_SIP_BASED_MBMS = 4; + + /** + * Security protocol param used with Generic Push Layer according to TS + * 33.224 as described in TS 33.220 Annex H. Mapped to byte stream + * "0x01,0x00,0x00,0x00,0x05". + */ + public static final int UA_SECURITY_PROTOCOL_3GPP_GENERIC_PUSH_LAYER = 5; + + /** + * Security protocol param used for IMS UE to KMS http based message + * exchanges according to "IMS media plane security", TS 33.328 as + * described in TS 33.220 Annex H. Mapped to byte stream + * "0x01,0x00,0x00,0x00,0x06". + */ + public static final int UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE = 6; + + /** + * Security protocol param used for Generation of Temporary IP + * Multimedia Private Identity (TMPI) according to TS 33.220 Annex B.4 + * Mapped to byte stream "0x01,0x00,0x00,0x01,0x00". + */ + public static final int UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI = 0x0100; + + /** + * Security protocol param used for Shared key-based UE authentication with + * certificate-based NAF authentication, according to TS 33.222 section 5.3, + * or Shared key-based mutual authentication between UE and NAF, according to + * TS 33.222 section 5.4. Mapped to byte stream "0x01,0x00,0x01,yy,zz". + * "yy, zz" is the TLS CipherSuite code. + */ + public static final int UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT = 0x010000; + + /** + * Security protocol param used for Shared key-based UE authentication with + * certificate-based NAF authentication, according to TS 33.222 Annex D. + * Mapped to byte stream "0x01,0x00,0x02,yy,zz". + * "yy, zz" is the TLS CipherSuite code. + */ + public static final int UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER = 0x020000; + + private static final int PROTOCOL_SIZE = 5; + private static final int[] sUaSp3gppIds = new int[] { + UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE, + UA_SECURITY_PROTOCOL_3GPP_MBMS, + UA_SECURITY_PROTOCOL_3GPP_HTTP_DIGEST_AUTHENTICATION, + UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS, + UA_SECURITY_PROTOCOL_3GPP_SIP_BASED_MBMS, + UA_SECURITY_PROTOCOL_3GPP_GENERIC_PUSH_LAYER, + UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE, + UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI, + UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT, + UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER}; + + private int mOrg; + private int mProtocol; + private int mTlsCipherSuite; + + private UaSecurityProtocolIdentifier() {} + + private UaSecurityProtocolIdentifier(UaSecurityProtocolIdentifier sp) { + mOrg = sp.mOrg; + mProtocol = sp.mProtocol; + mTlsCipherSuite = sp.mTlsCipherSuite; + } + + /** + * Returns the byte array representing the ua security protocol + */ + @NonNull + public byte[] toByteArray() { + byte[] data = new byte[PROTOCOL_SIZE]; + ByteBuffer buf = ByteBuffer.wrap(data); + buf.put((byte) mOrg); + buf.putInt(mProtocol | mTlsCipherSuite); + return data; + } + + /** + * Returns the organization code + */ + public @OrganizationCode int getOrg() { + return mOrg; + } + + /** + * Returns the security procotol id + * + * <p>Note that only 3GPP UA Security Protocols are supported for now + */ + public @UaSecurityProtocol3gpp int getProtocol() { + return mProtocol; + } + + /** + * Returns the TLS cipher suite + */ + public @TlsCipherSuite int getTlsCipherSuite() { + return mTlsCipherSuite; + } + + /** + * {@link Parcelable#writeToParcel} + */ + @Override + public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeInt(mOrg); + out.writeInt(mProtocol); + out.writeInt(mTlsCipherSuite); + } + + /** + * {@link Parcelable.Creator} + * + */ + public static final @NonNull Parcelable.Creator< + UaSecurityProtocolIdentifier> CREATOR = new Creator<UaSecurityProtocolIdentifier>() { + @Nullable + @Override + public UaSecurityProtocolIdentifier createFromParcel(Parcel in) { + int org = in.readInt(); + int protocol = in.readInt(); + int cs = in.readInt(); + if (org < 0 || protocol < 0 || cs < 0) { + return null; + } + Builder builder = new Builder(); + try { + if (org > 0) { + builder.setOrg(org); + } + if (protocol > 0) { + builder.setProtocol(protocol); + } + if (cs > 0) { + builder.setTlsCipherSuite(cs); + } + } catch (IllegalArgumentException e) { + return null; + } + return builder.build(); + } + + @NonNull + @Override + public UaSecurityProtocolIdentifier[] newArray(int size) { + return new UaSecurityProtocolIdentifier[size]; + } + }; + + /** + * {@link Parcelable#describeContents} + */ + @Override + public int describeContents() { + return 0; + } + + @Override + public String toString() { + return "UaSecurityProtocolIdentifier[" + mOrg + " , " + (mProtocol | mTlsCipherSuite) + "]"; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof UaSecurityProtocolIdentifier)) { + return false; + } + + UaSecurityProtocolIdentifier other = (UaSecurityProtocolIdentifier) obj; + + return mOrg == other.mOrg && mProtocol == other.mProtocol + && mTlsCipherSuite == other.mTlsCipherSuite; + } + + @Override + public int hashCode() { + return Objects.hash(mOrg, mProtocol, mTlsCipherSuite); + } + + private boolean isTlsSupported() { + //TODO May update to support non 3gpp protocol in the future + if (mOrg == ORG_3GPP && (mProtocol == UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT + || mProtocol == UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER)) { + return true; + } + + return false; + } + + /** + * Builder class for UaSecurityProtocolIdentifier + */ + public static final class Builder { + private final UaSecurityProtocolIdentifier mSp; + + /** + * Creates a Builder with default UaSecurityProtocolIdentifier, a.k.a 0x00 00 00 00 00 + */ + public Builder() { + mSp = new UaSecurityProtocolIdentifier(); + } + + /** + * Creates a Builder from a UaSecurityProtocolIdentifier + */ + public Builder(@NonNull final UaSecurityProtocolIdentifier sp) { + Objects.requireNonNull(sp); + mSp = new UaSecurityProtocolIdentifier(sp); + } + + /** + * Sets the organization code + * + * @param orgCode the organization code with the following value + * <ol> + * <li>{@link #ORG_NONE} </li> + * <li>{@link #ORG_3GPP} </li> + * <li>{@link #ORG_3GPP2} </li> + * <li>{@link #ORG_OMA} </li> + * <li>{@link #ORG_GSMA} </li> + * <li>{@link #ORG_LOCAL} </li> + * </ol> + * @throws IllegalArgumentException if it is not one of the value above. + * + * <p>Note that this method will reset the security protocol and TLS cipher suite + * if they have been set. + */ + @NonNull + public Builder setOrg(@OrganizationCode int orgCode) { + if (orgCode < ORG_NONE || orgCode > ORG_LOCAL) { + throw new IllegalArgumentException("illegal organization code"); + } + mSp.mOrg = orgCode; + mSp.mProtocol = 0; + mSp.mTlsCipherSuite = 0; + return this; + } + + /** + * Sets the UA security protocol for 3GPP + * + * @param protocol only 3GPP ua security protocol ID is supported for now, which + * is one of the following value + * <ol> + * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE} </li> + * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_MBMS} </li> + * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_HTTP_DIGEST_AUTHENTICATION} </li> + * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS} </li> + * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_SIP_BASED_MBMS} </li> + * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_GENERIC_PUSH_LAYER} </li> + * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE} </li> + * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI} </li> + * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT} </li> + * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER} </li> + * </ol> + * @throws IllegalArgumentException if the protocol is not one of the value above. + * + * <p>Note that this method will reset TLS cipher suite if it has been set. + */ + @NonNull + public Builder setProtocol(@UaSecurityProtocol3gpp int protocol) { + //TODO May update to support non 3gpp protocol in the future + if (protocol < UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE + || (protocol > UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE + && protocol != UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI + && protocol != UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT + && protocol != UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER) + || mSp.mOrg != ORG_3GPP) { + throw new IllegalArgumentException("illegal protocol code"); + } + mSp.mProtocol = protocol; + mSp.mTlsCipherSuite = 0; + return this; + } + + /** + * Sets the UA security protocol for 3GPP + * + * @param cs TLS cipher suite value defined by {@link TlsParams#TlsCipherSuite} + * @throws IllegalArgumentException if it is not a 3GPP ua security protocol, + * the protocol does not support TLS, or does not support the cipher suite. + */ + @NonNull + public Builder setTlsCipherSuite(@TlsCipherSuite int cs) { + if (!mSp.isTlsSupported()) { + throw new IllegalArgumentException("The protocol does not support TLS"); + } + if (!TlsParams.isTlsCipherSuiteSupported(cs)) { + throw new IllegalArgumentException("TLS cipher suite is not supported"); + } + mSp.mTlsCipherSuite = cs; + return this; + } + + /** + * Builds the instance of UaSecurityProtocolIdentifier + * + * @return the built instance of UaSecurityProtocolIdentifier + */ + @NonNull + public UaSecurityProtocolIdentifier build() { + return new UaSecurityProtocolIdentifier(mSp); + } + } +} diff --git a/telephony/java/android/telephony/gsm/OWNERS b/telephony/java/android/telephony/gsm/OWNERS new file mode 100644 index 000000000000..6aa399d9ebfb --- /dev/null +++ b/telephony/java/android/telephony/gsm/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +amitmahajan@google.com diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java index 184477af0b46..c14024975cf5 100644 --- a/telephony/java/android/telephony/ims/ImsReasonInfo.java +++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java @@ -1322,6 +1322,13 @@ public final class ImsReasonInfo implements Parcelable { */ public static final int EXTRA_CODE_CALL_RETRY_BY_SETTINGS = 3; + /** + * An extra that may be populated when the {@link #CODE_LOCAL_CALL_CS_RETRY_REQUIRED} result has + * been returned. + * <p> + * Try to connect the call using CS as emergency + */ + public static final int EXTRA_CODE_CALL_RETRY_EMERGENCY = 4; // For main reason code /** @hide */ diff --git a/telephony/java/android/telephony/ims/OWNERS b/telephony/java/android/telephony/ims/OWNERS new file mode 100644 index 000000000000..0854c5d45603 --- /dev/null +++ b/telephony/java/android/telephony/ims/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +breadley@google.com diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl index b47e3c75b558..10c50bed34d7 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl @@ -22,7 +22,6 @@ import android.telephony.ims.aidl.ICapabilityExchangeEventListener; import android.telephony.ims.aidl.IImsCapabilityCallback; import android.telephony.ims.aidl.IOptionsResponseCallback; import android.telephony.ims.aidl.IPublishResponseCallback; -import android.telephony.ims.aidl.IRcsFeatureListener; import android.telephony.ims.aidl.ISubscribeResponseCallback; import android.telephony.ims.feature.CapabilityChangeRequest; @@ -34,7 +33,6 @@ import java.util.List; */ interface IImsRcsFeature { // Not oneway because we need to verify this completes before doing anything else. - void setListener(IRcsFeatureListener listener); int queryCapabilityStatus(); // Inherited from ImsFeature int getFeatureState(); @@ -50,14 +48,4 @@ interface IImsRcsFeature { oneway void subscribeForCapabilities(in List<Uri> uris, ISubscribeResponseCallback cb); oneway void sendOptionsCapabilityRequest(in Uri contactUri, in List<String> myCapabilities, IOptionsResponseCallback cb); - // RcsPresenceExchangeImplBase specific api - oneway void requestCapabilities(in List<Uri> uris, int operationToken); - oneway void updateCapabilities(in RcsContactUceCapability capabilities, int operationToken); - // RcsSipOptionsImplBase specific api - oneway void sendCapabilityRequest(in Uri contactUri, - in RcsContactUceCapability capabilities, int operationToken); - oneway void respondToCapabilityRequest(in String contactUri, - in RcsContactUceCapability ownCapabilities, int operationToken); - oneway void respondToCapabilityRequestWithError(in Uri contactUri, int code, in String reason, - int operationToken); } diff --git a/telephony/java/android/telephony/ims/aidl/IRcsFeatureListener.aidl b/telephony/java/android/telephony/ims/aidl/IRcsFeatureListener.aidl deleted file mode 100644 index 70cf651d3924..000000000000 --- a/telephony/java/android/telephony/ims/aidl/IRcsFeatureListener.aidl +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.telephony.ims.aidl; - -import android.net.Uri; -import android.telephony.ims.RcsContactUceCapability; - -import java.util.List; - -/** - * Listener interface for updates from the RcsFeature back to the framework. - * {@hide} - */ -interface IRcsFeatureListener { - //RcsCapabilityExchange specific - oneway void onCommandUpdate(int commandCode, int operationToken); - // RcsPresenceExchangeImplBase Specific - oneway void onNetworkResponse(int code, in String reason, int operationToken); - oneway void onCapabilityRequestResponsePresence(in List<RcsContactUceCapability> infos, - int operationToken); - oneway void onNotifyUpdateCapabilities(int publishTriggerType); - oneway void onUnpublish(); - // RcsSipOptionsImplBase specific - oneway void onCapabilityRequestResponseOptions(int code, in String reason, - in RcsContactUceCapability info, int operationToken); - oneway void onRemoteCapabilityRequest(in Uri contactUri, in RcsContactUceCapability remoteInfo, - int operationToken); -} diff --git a/telephony/java/android/telephony/ims/aidl/OWNERS b/telephony/java/android/telephony/ims/aidl/OWNERS new file mode 100644 index 000000000000..0854c5d45603 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +breadley@google.com diff --git a/telephony/java/android/telephony/ims/compat/OWNERS b/telephony/java/android/telephony/ims/compat/OWNERS new file mode 100644 index 000000000000..0854c5d45603 --- /dev/null +++ b/telephony/java/android/telephony/ims/compat/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +breadley@google.com diff --git a/telephony/java/android/telephony/ims/compat/feature/OWNERS b/telephony/java/android/telephony/ims/compat/feature/OWNERS new file mode 100644 index 000000000000..0854c5d45603 --- /dev/null +++ b/telephony/java/android/telephony/ims/compat/feature/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +breadley@google.com diff --git a/telephony/java/android/telephony/ims/compat/stub/OWNERS b/telephony/java/android/telephony/ims/compat/stub/OWNERS new file mode 100644 index 000000000000..0854c5d45603 --- /dev/null +++ b/telephony/java/android/telephony/ims/compat/stub/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +breadley@google.com diff --git a/telephony/java/android/telephony/ims/feature/OWNERS b/telephony/java/android/telephony/ims/feature/OWNERS new file mode 100644 index 000000000000..0854c5d45603 --- /dev/null +++ b/telephony/java/android/telephony/ims/feature/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +breadley@google.com diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java index 5de2ddc578a1..cde7067e8bf3 100644 --- a/telephony/java/android/telephony/ims/feature/RcsFeature.java +++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java @@ -19,17 +19,16 @@ package android.telephony.ims.feature; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.Uri; import android.os.RemoteException; -import android.telephony.ims.RcsContactUceCapability; import android.telephony.ims.RcsUceAdapter; import android.telephony.ims.aidl.ICapabilityExchangeEventListener; import android.telephony.ims.aidl.IImsCapabilityCallback; import android.telephony.ims.aidl.IImsRcsFeature; import android.telephony.ims.aidl.IOptionsResponseCallback; import android.telephony.ims.aidl.IPublishResponseCallback; -import android.telephony.ims.aidl.IRcsFeatureListener; import android.telephony.ims.aidl.ISubscribeResponseCallback; import android.telephony.ims.aidl.RcsOptionsResponseAidlWrapper; import android.telephony.ims.aidl.RcsPublishResponseAidlWrapper; @@ -74,16 +73,6 @@ public class RcsFeature extends ImsFeature { mExecutor = executor; } - /** - * @deprecated This method is deprecated. Please call the method - * setCapabilityExchangeEventListener instead. - */ - @Override - @Deprecated - public void setListener(IRcsFeatureListener listener) { - Log.w(LOG_TAG, "The method setListener is deprecated"); - } - @Override public int queryCapabilityStatus() throws RemoteException { return executeMethodAsyncForResult( @@ -124,7 +113,7 @@ public class RcsFeature extends ImsFeature { // RcsCapabilityExchangeImplBase specific APIs @Override public void setCapabilityExchangeEventListener( - @NonNull ICapabilityExchangeEventListener listener) throws RemoteException { + @Nullable ICapabilityExchangeEventListener listener) throws RemoteException { executeMethodAsync(() -> mReference.setCapabilityExchangeEventListener(listener), "setCapabilityExchangeEventListener"); } @@ -155,34 +144,6 @@ public class RcsFeature extends ImsFeature { "sendOptionsCapabilityRequest"); } - // RcsPresenceExchangeImplBase specific APIS - @Override - public void requestCapabilities(List<Uri> uris, int operationToken) throws RemoteException { - throw new RemoteException("Unsupported operation: requestCapabilities"); - } - @Override - public void updateCapabilities(RcsContactUceCapability capabilities, int operationToken) - throws RemoteException { - throw new RemoteException("Unsupported operation: updateCapabilities"); - } - // RcsSipOptionsImplBase specific APIS - @Override - public void sendCapabilityRequest(Uri contactUri, RcsContactUceCapability capabilities, - int operationToken) throws RemoteException { - throw new RemoteException("Unsupported operation: sendCapabilityRequest"); - } - @Override - public void respondToCapabilityRequest(String contactUri, - RcsContactUceCapability ownCapabilities, int operationToken) - throws RemoteException { - throw new RemoteException("Unsupported operation: respondToCapabilityRequest"); - } - @Override - public void respondToCapabilityRequestWithError(Uri contactUri, int code, String reason, - int operationToken) throws RemoteException { - throw new RemoteException("Unsupported operation: respondToCapabilityRequestWithError"); - } - // Call the methods with a clean calling identity on the executor and wait indefinitely for // the future to return. private void executeMethodAsync(Runnable r, String errorLogName) diff --git a/telephony/java/android/telephony/ims/stub/OWNERS b/telephony/java/android/telephony/ims/stub/OWNERS new file mode 100644 index 000000000000..0854c5d45603 --- /dev/null +++ b/telephony/java/android/telephony/ims/stub/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +breadley@google.com diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java deleted file mode 100644 index 0b13efb7b4b4..000000000000 --- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.telephony.ims.stub; - -import android.annotation.IntDef; -import android.os.RemoteException; -import android.telephony.ims.ImsException; -import android.telephony.ims.aidl.IRcsFeatureListener; -import android.telephony.ims.feature.ImsFeature; -import android.telephony.ims.feature.RcsFeature; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Base class for different types of Capability exchange, presence using - * {@link RcsPresenceExchangeImplBase} and SIP OPTIONS exchange using {@link RcsSipOptionsImplBase}. - * - * @hide - */ -public class RcsCapabilityExchange { - - /** Service is unknown. */ - public static final int COMMAND_CODE_SERVICE_UNKNOWN = 0; - /** The command completed successfully. */ - public static final int COMMAND_CODE_SUCCESS = 1; - /** The command failed with an unknown error. */ - public static final int COMMAND_CODE_GENERIC_FAILURE = 2; - /** Invalid parameter(s). */ - public static final int COMMAND_CODE_INVALID_PARAM = 3; - /** Fetch error. */ - public static final int COMMAND_CODE_FETCH_ERROR = 4; - /** Request timed out. */ - public static final int COMMAND_CODE_REQUEST_TIMEOUT = 5; - /** Failure due to insufficient memory available. */ - public static final int COMMAND_CODE_INSUFFICIENT_MEMORY = 6; - /** Network connection is lost. */ - public static final int COMMAND_CODE_LOST_NETWORK_CONNECTION = 7; - /** Requested feature/resource is not supported. */ - public static final int COMMAND_CODE_NOT_SUPPORTED = 8; - /** Contact or resource is not found. */ - public static final int COMMAND_CODE_NOT_FOUND = 9; - /** Service is not available. */ - public static final int COMMAND_CODE_SERVICE_UNAVAILABLE = 10; - /** No Change in Capabilities */ - public static final int COMMAND_CODE_NO_CHANGE_IN_CAP = 11; - - /** @hide*/ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = "COMMAND_CODE_", value = { - COMMAND_CODE_SERVICE_UNKNOWN, - COMMAND_CODE_SUCCESS, - COMMAND_CODE_GENERIC_FAILURE, - COMMAND_CODE_INVALID_PARAM, - COMMAND_CODE_FETCH_ERROR, - COMMAND_CODE_REQUEST_TIMEOUT, - COMMAND_CODE_INSUFFICIENT_MEMORY, - COMMAND_CODE_LOST_NETWORK_CONNECTION, - COMMAND_CODE_NOT_SUPPORTED, - COMMAND_CODE_NOT_FOUND, - COMMAND_CODE_SERVICE_UNAVAILABLE, - COMMAND_CODE_NO_CHANGE_IN_CAP - }) - public @interface CommandCode {} - - - private RcsFeature mFeature; - - /** @hide */ - public final void initialize(RcsFeature feature) { - mFeature = feature; - } - - /** @hide */ - protected final IRcsFeatureListener getListener() throws ImsException { - throw new ImsException("This method is deprecated.", - ImsException.CODE_ERROR_UNSUPPORTED_OPERATION); - } - - /** - * Provides the framework with an update as to whether or not a command completed successfully - * locally. This includes capabilities requests and updates from the network. If it does not - * complete successfully, then the framework may retry the command again later, depending on the - * error. If the command does complete successfully, the framework will then wait for network - * updates. - * - * @param code The result of the pending command. If {@link #COMMAND_CODE_SUCCESS}, further - * updates will be sent for this command using the associated operationToken. - * @param operationToken the token associated with the pending command. - * @throws ImsException If this {@link RcsCapabilityExchange} instance is not currently - * connected to the framework. This can happen if the {@link RcsFeature} is not - * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the - * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the - * Telephony stack has crashed. - */ - public final void onCommandUpdate(@CommandCode int code, int operationToken) - throws ImsException { - try { - getListener().onCommandUpdate(code, operationToken); - } catch (RemoteException e) { - throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); - } - } -} diff --git a/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java deleted file mode 100644 index bb034489a296..000000000000 --- a/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.telephony.ims.stub; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.net.Uri; -import android.os.RemoteException; -import android.telephony.ims.ImsException; -import android.telephony.ims.RcsContactUceCapability; -import android.telephony.ims.feature.ImsFeature; -import android.telephony.ims.feature.RcsFeature; -import android.util.Log; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.List; - -/** - * Base implementation for RCS User Capability Exchange using Presence. Any ImsService implementing - * this service must implement the stub methods {@link #requestCapabilities(List, int)} and - * {@link #updateCapabilities(RcsContactUceCapability, int)}. - * - * @hide - */ -public class RcsPresenceExchangeImplBase extends RcsCapabilityExchange { - - private static final String LOG_TAG = "RcsPresenceExchangeIB"; - - /** - * The request has resulted in any other 4xx/5xx/6xx that is not covered below. No retry will be - * attempted. - */ - public static final int RESPONSE_SUBSCRIBE_GENERIC_FAILURE = -1; - - /** - * The request has succeeded with a “200” message from the network. - */ - public static final int RESPONSE_SUCCESS = 0; - - /** - * The request has resulted in a “403” (User Not Registered) error from the network. Will retry - * capability polling with an exponential backoff. - */ - public static final int RESPONSE_NOT_REGISTERED = 1; - - /** - * The request has resulted in a “403” (not authorized (Requestor)) error from the network. No - * retry will be attempted. - */ - public static final int RESPONSE_NOT_AUTHORIZED_FOR_PRESENCE = 2; - - /** - * The request has resulted in a "403” (Forbidden) or other “403” error from the network and - * will be handled the same as “404” Not found. No retry will be attempted. - */ - public static final int RESPONSE_FORBIDDEN = 3; - - /** - * The request has resulted in a “404” (Not found) result from the network. No retry will be - * attempted. - */ - public static final int RESPONSE_NOT_FOUND = 4; - - /** - * The request has resulted in a “408” response. Retry after exponential backoff. - */ - public static final int RESPONSE_SIP_REQUEST_TIMEOUT = 5; - - /** - * The network has responded with a “413” (Too Large) response from the network. Capability - * request contains too many items and must be shrunk before the request will be accepted. - */ - public static final int RESPONSE_SUBSCRIBE_TOO_LARGE = 6; - - /** - * The request has resulted in a “423” response. Retry after exponential backoff. - */ - public static final int RESPONSE_SIP_INTERVAL_TOO_SHORT = 7; - - /** - * The request has resulted in a “503” response. Retry after exponential backoff. - */ - public static final int RESPONSE_SIP_SERVICE_UNAVAILABLE = 8; - - /** @hide*/ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = "RESPONSE_", value = { - RESPONSE_SUBSCRIBE_GENERIC_FAILURE, - RESPONSE_SUCCESS, - RESPONSE_NOT_REGISTERED, - RESPONSE_NOT_AUTHORIZED_FOR_PRESENCE, - RESPONSE_FORBIDDEN, - RESPONSE_NOT_FOUND, - RESPONSE_SIP_REQUEST_TIMEOUT, - RESPONSE_SUBSCRIBE_TOO_LARGE, - RESPONSE_SIP_INTERVAL_TOO_SHORT, - RESPONSE_SIP_SERVICE_UNAVAILABLE - }) - public @interface PresenceResponseCode {} - - - /** A capability update has been requested due to the Entity Tag (ETag) expiring. */ - public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 0; - /** A capability update has been requested due to moving to LTE with VoPS disabled. */ - public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 1; - /** A capability update has been requested due to moving to LTE with VoPS enabled. */ - public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 2; - /** A capability update has been requested due to moving to eHRPD. */ - public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 3; - /** A capability update has been requested due to moving to HSPA+. */ - public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 4; - /** A capability update has been requested due to moving to 3G. */ - public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 5; - /** A capability update has been requested due to moving to 2G. */ - public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 6; - /** A capability update has been requested due to moving to WLAN */ - public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN = 7; - /** A capability update has been requested due to moving to IWLAN */ - public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 8; - /** A capability update has been requested but the reason is unknown. */ - public static final int CAPABILITY_UPDATE_TRIGGER_UNKNOWN = 9; - /** A capability update has been requested due to moving to 5G NR with VoPS disabled. */ - public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED = 10; - /** A capability update has been requested due to moving to 5G NR with VoPS enabled. */ - public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11; - - /** @hide*/ - @IntDef(value = { - CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED, - CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED, - CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED, - CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD, - CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS, - CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G, - CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G, - CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN, - CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN, - CAPABILITY_UPDATE_TRIGGER_UNKNOWN, - CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED, - CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED - }, prefix = "CAPABILITY_UPDATE_TRIGGER_") - @Retention(RetentionPolicy.SOURCE) - public @interface StackPublishTriggerType { - } - - /** - * Provide the framework with a subsequent network response update to - * {@link #updateCapabilities(RcsContactUceCapability, int)} and - * {@link #requestCapabilities(List, int)} operations. - * - * @param code The SIP response code sent from the network for the operation token specified. - * @param reason The optional reason response from the network. If the network provided no - * reason with the code, the string should be empty. - * @param operationToken The token associated with the operation this service is providing a - * response for. - * @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is not currently - * connected to the framework. This can happen if the {@link RcsFeature} is not - * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the - * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the - * Telephony stack has crashed. - */ - public final void onNetworkResponse(@PresenceResponseCode int code, @NonNull String reason, - int operationToken) throws ImsException { - try { - getListener().onNetworkResponse(code, reason, operationToken); - } catch (RemoteException e) { - throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); - } - } - - /** - * Provides the framework with the requested contacts’ capabilities requested by the framework - * using {@link #requestCapabilities(List, int)}. - * - * @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is not currently - * connected to the framework. This can happen if the {@link RcsFeature} is not - * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the - * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the - * Telephony stack has crashed. - */ - public final void onCapabilityRequestResponse(@NonNull List<RcsContactUceCapability> infos, - int operationToken) throws ImsException { - try { - getListener().onCapabilityRequestResponsePresence(infos, operationToken); - } catch (RemoteException e) { - throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); - } - } - - /** - * Trigger the framework to provide a capability update using - * {@link #updateCapabilities(RcsContactUceCapability, int)}. - * <p> - * This is typically used when trying to generate an initial PUBLISH for a new subscription to - * the network. The device will cache all presence publications after boot until this method is - * called once. - * @param publishTriggerType {@link StackPublishTriggerType} The reason for the capability - * update request. - * @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is not currently - * connected to the framework. This can happen if the {@link RcsFeature} is not - * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the - * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the - * Telephony stack has crashed. - */ - public final void onNotifyUpdateCapabilites(@StackPublishTriggerType int publishTriggerType) - throws ImsException { - try { - getListener().onNotifyUpdateCapabilities(publishTriggerType); - } catch (RemoteException e) { - throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); - } - } - - /** - * Notify the framework that the device’s capabilities have been unpublished from the network. - * - * @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is not currently - * connected to the framework. This can happen if the {@link RcsFeature} is not - * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the - * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the - * Telephony stack has crashed. - */ - public final void onUnpublish() throws ImsException { - try { - getListener().onUnpublish(); - } catch (RemoteException e) { - throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); - } - } - - /** - * The user capabilities of one or multiple contacts have been requested by the framework. - * <p> - * The implementer must follow up this call with an {@link #onCommandUpdate(int, int)} call to - * indicate whether or not this operation succeeded. If this operation succeeds, network - * response updates should be sent to the framework using - * {@link #onNetworkResponse(int, String, int)}. When the operation is completed, - * {@link #onCapabilityRequestResponse(List, int)} should be called with the presence - * information for the contacts specified. - * @param uris A {@link List} of the {@link Uri}s that the framework is requesting the UCE - * capabilities for. - * @param operationToken The token associated with this operation. Updates to this request using - * {@link #onCommandUpdate(int, int)}, {@link #onNetworkResponse(int, String, int)}, and - * {@link #onCapabilityRequestResponse(List, int)} must use the same operation token - * in response. - */ - public void requestCapabilities(@NonNull List<Uri> uris, int operationToken) { - // Stub - to be implemented by service - Log.w(LOG_TAG, "requestCapabilities called with no implementation."); - try { - getListener().onCommandUpdate(COMMAND_CODE_NOT_SUPPORTED, operationToken); - } catch (RemoteException | ImsException e) { - // Do not do anything, this is a stub implementation. - } - } - - /** - * The capabilities of this device have been updated and should be published to the network. - * <p> - * The implementer must follow up this call with an {@link #onCommandUpdate(int, int)} call to - * indicate whether or not this operation succeeded. If this operation succeeds, network - * response updates should be sent to the framework using - * {@link #onNetworkResponse(int, String, int)}. - * @param capabilities The capabilities for this device. - * @param operationToken The token associated with this operation. Any subsequent - * {@link #onCommandUpdate(int, int)} or {@link #onNetworkResponse(int, String, int)} - * calls regarding this update must use the same token. - */ - public void updateCapabilities(@NonNull RcsContactUceCapability capabilities, - int operationToken) { - // Stub - to be implemented by service - Log.w(LOG_TAG, "updateCapabilities called with no implementation."); - try { - getListener().onCommandUpdate(COMMAND_CODE_NOT_SUPPORTED, operationToken); - } catch (RemoteException | ImsException e) { - // Do not do anything, this is a stub implementation. - } - } -} diff --git a/telephony/java/android/telephony/ims/stub/RcsSipOptionsImplBase.java b/telephony/java/android/telephony/ims/stub/RcsSipOptionsImplBase.java deleted file mode 100644 index 2035fac4fae0..000000000000 --- a/telephony/java/android/telephony/ims/stub/RcsSipOptionsImplBase.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.telephony.ims.stub; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.Uri; -import android.os.RemoteException; -import android.telephony.ims.ImsException; -import android.telephony.ims.RcsContactUceCapability; -import android.telephony.ims.feature.ImsFeature; -import android.telephony.ims.feature.RcsFeature; -import android.util.Log; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Base implementation for RCS User Capability Exchange using SIP OPTIONS. - * - * @hide - */ -public class RcsSipOptionsImplBase extends RcsCapabilityExchange { - - private static final String LOG_TAG = "RcsSipOptionsImplBase"; - - /** - * Indicates a SIP response from the remote user other than 200, 480, 408, 404, or 604. - */ - public static final int RESPONSE_GENERIC_FAILURE = -1; - - /** - * Indicates that the remote user responded with a 200 OK response. - */ - public static final int RESPONSE_SUCCESS = 0; - - /** - * Indicates that the remote user responded with a 480 TEMPORARY UNAVAILABLE response. - */ - public static final int RESPONSE_TEMPORARILY_UNAVAILABLE = 1; - - /** - * Indicates that the remote user responded with a 408 REQUEST TIMEOUT response. - */ - public static final int RESPONSE_REQUEST_TIMEOUT = 2; - - /** - * Indicates that the remote user responded with a 404 NOT FOUND response. - */ - public static final int RESPONSE_NOT_FOUND = 3; - - /** - * Indicates that the remote user responded with a 604 DOES NOT EXIST ANYWHERE response. - */ - public static final int RESPONSE_DOES_NOT_EXIST_ANYWHERE = 4; - - /** - * Indicates that the remote user responded with a 400 BAD REQUEST response. - */ - public static final int RESPONSE_BAD_REQUEST = 5; - - /** @hide*/ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = "RESPONSE_", value = { - RESPONSE_GENERIC_FAILURE, - RESPONSE_SUCCESS, - RESPONSE_TEMPORARILY_UNAVAILABLE, - RESPONSE_REQUEST_TIMEOUT, - RESPONSE_NOT_FOUND, - RESPONSE_DOES_NOT_EXIST_ANYWHERE, - RESPONSE_BAD_REQUEST - }) - public @interface SipResponseCode {} - - /** - * Send the response of a SIP OPTIONS capability exchange to the framework. If {@code code} is - * {@link #RESPONSE_SUCCESS}, info must be non-null. - * @param code The SIP response code that was sent by the network in response to the request - * sent by {@link #sendCapabilityRequest(Uri, RcsContactUceCapability, int)}. - * @param reason The optional SIP response reason sent by the network. If none was sent, this - * should be an empty string. - * @param info the contact's UCE capabilities associated with the capability request. - * @param operationToken The token associated with the original capability request, set by - * {@link #sendCapabilityRequest(Uri, RcsContactUceCapability, int)}. - * @throws ImsException If this {@link RcsSipOptionsImplBase} instance is not currently - * connected to the framework. This can happen if the {@link RcsFeature} is not - * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the - * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the - * Telephony stack has crashed. - */ - public final void onCapabilityRequestResponse(@SipResponseCode int code, @NonNull String reason, - @Nullable RcsContactUceCapability info, int operationToken) throws ImsException { - try { - getListener().onCapabilityRequestResponseOptions(code, reason, info, operationToken); - } catch (RemoteException e) { - throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); - } - } - - /** - * Inform the framework of a query for this device's UCE capabilities. - * <p> - * The framework will respond via the - * {@link #respondToCapabilityRequest(String, RcsContactUceCapability, int)} or - * {@link #respondToCapabilityRequestWithError(Uri, int, String, int)} method. - * @param contactUri The URI associated with the remote contact that is requesting capabilities. - * @param remoteInfo The remote contact's capability information. - * @param operationToken An unique operation token that you have generated that will be returned - * by the framework in - * {@link #respondToCapabilityRequest(String, RcsContactUceCapability, int)}. - * @throws ImsException If this {@link RcsSipOptionsImplBase} instance is not currently - * connected to the framework. This can happen if the {@link RcsFeature} is not - * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the - * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the - * Telephony stack has crashed. - */ - public final void onRemoteCapabilityRequest(@NonNull Uri contactUri, - @NonNull RcsContactUceCapability remoteInfo, int operationToken) throws ImsException { - try { - getListener().onRemoteCapabilityRequest(contactUri, remoteInfo, operationToken); - } catch (RemoteException e) { - throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); - } - } - - /** - * Push one's own capabilities to a remote user via the SIP OPTIONS presence exchange mechanism - * in order to receive the capabilities of the remote user in response. - * <p> - * The implementer must call - * {@link #onCapabilityRequestResponse(int, String, RcsContactUceCapability, int)} to send the - * response of this query back to the framework. - * @param contactUri The URI of the remote user that we wish to get the capabilities of. - * @param capabilities The capabilities of this device to send to the remote user. - * @param operationToken A token generated by the framework that will be passed through - * {@link #onCapabilityRequestResponse(int, String, RcsContactUceCapability, int)} when this - * operation has succeeded. - */ - public void sendCapabilityRequest(@NonNull Uri contactUri, - @NonNull RcsContactUceCapability capabilities, int operationToken) { - // Stub - to be implemented by service - Log.w(LOG_TAG, "sendCapabilityRequest called with no implementation."); - try { - getListener().onCommandUpdate(COMMAND_CODE_NOT_SUPPORTED, operationToken); - } catch (RemoteException | ImsException e) { - // Do not do anything, this is a stub implementation. - } - } - - /** - * Respond to a remote capability request from the contact specified with the capabilities of - * this device. - * <p> - * The framework will use the same token and uri as what was passed in to - * {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)}. - * @param contactUri The URI of the remote contact. - * @param ownCapabilities The capabilities of this device. - * @param operationToken The token generated by the framework that this service obtained when - * {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)} was called. - */ - public void respondToCapabilityRequest(@NonNull String contactUri, - @NonNull RcsContactUceCapability ownCapabilities, int operationToken) { - // Stub - to be implemented by service - Log.w(LOG_TAG, "respondToCapabilityRequest called with no implementation."); - try { - getListener().onCommandUpdate(COMMAND_CODE_NOT_SUPPORTED, operationToken); - } catch (RemoteException | ImsException e) { - // Do not do anything, this is a stub implementation. - } - } - - /** - * Respond to a remote capability request from the contact specified with the specified error. - * <p> - * The framework will use the same token and uri as what was passed in to - * {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)}. - * @param contactUri A URI containing the remote contact. - * @param code The SIP response code to respond with. - * @param reason A non-null String containing the reason associated with the SIP code. - * @param operationToken The token provided by the framework when - * {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)} was called. - */ - public void respondToCapabilityRequestWithError(@NonNull Uri contactUri, - @SipResponseCode int code, @NonNull String reason, int operationToken) { - // Stub - to be implemented by service - Log.w(LOG_TAG, "respondToCapabiltyRequestWithError called with no implementation."); - try { - getListener().onCommandUpdate(COMMAND_CODE_NOT_SUPPORTED, operationToken); - } catch (RemoteException | ImsException e) { - // Do not do anything, this is a stub implementation. - } - } -} diff --git a/telephony/java/android/telephony/mbms/OWNERS b/telephony/java/android/telephony/mbms/OWNERS new file mode 100644 index 000000000000..718e0a292605 --- /dev/null +++ b/telephony/java/android/telephony/mbms/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +hallliu@google.com diff --git a/telephony/java/android/telephony/mbms/vendor/OWNERS b/telephony/java/android/telephony/mbms/vendor/OWNERS new file mode 100644 index 000000000000..718e0a292605 --- /dev/null +++ b/telephony/java/android/telephony/mbms/vendor/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 20868 + +rgreenwalt@google.com +tgunn@google.com +hallliu@google.com diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl index 09f9b4212c03..ce2017bb9a35 100644 --- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl +++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl @@ -216,5 +216,6 @@ interface IPhoneSubInfo { * @param data authentication challenge data * @return challenge response */ - String getIccSimChallengeResponse(int subId, int appType, int authType, String data); + String getIccSimChallengeResponse(int subId, int appType, int authType, String data, + String callingPackage, String callingFeatureId); } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 5d4fdd0ff556..2da45ca32584 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -37,6 +37,8 @@ import android.telephony.CellIdentity; import android.telephony.CellInfo; import android.telephony.ClientRequestStats; import android.telephony.ThermalMitigationRequest; +import android.telephony.gba.UaSecurityProtocolIdentifier; +import android.telephony.IBootstrapAuthenticationCallback; import android.telephony.IccOpenLogicalChannelResponse; import android.telephony.ICellInfoCallback; import android.telephony.ModemActivityInfo; @@ -1674,10 +1676,19 @@ interface ITelephony { * @param slotIndex SIM slot id * @param state State of SIM (power down, power up, pass through) * @hide - * */ + */ void setSimPowerStateForSlot(int slotIndex, int state); /** + * Set SIM card power state. + * @param slotIndex SIM slot id + * @param state State of SIM (power down, power up, pass through) + * @param callback callback to receive result info + * @hide + */ + void setSimPowerStateForSlotWithCallback(int slotIndex, int state, IIntegerConsumer callback); + + /** * Returns a list of Forbidden PLMNs from the specified SIM App * Returns null if the query fails. * @@ -2273,4 +2284,31 @@ interface ITelephony { */ int sendThermalMitigationRequest(int subId, in ThermalMitigationRequest thermalMitigationRequest); + + /** + * get the Generic Bootstrapping Architecture authentication keys + */ + void bootstrapAuthenticationRequest(int subId, int appType, in Uri nafUrl, + in UaSecurityProtocolIdentifier securityProtocol, + boolean forceBootStrapping, IBootstrapAuthenticationCallback callback); + + /** + * Set the GbaService Package Name that Telephony will bind to. + */ + boolean setBoundGbaServiceOverride(int subId, String packageName); + + /** + * Return the package name of the currently bound GbaService. + */ + String getBoundGbaService(int subId); + + /** + * Set the release time for telephony to unbind GbaService. + */ + boolean setGbaReleaseTimeOverride(int subId, int interval); + + /** + * Return the release time for telephony to unbind GbaService. + */ + int getGbaReleaseTime(int subId); } diff --git a/tests/ActivityManagerPerfTests/OWNERS b/tests/ActivityManagerPerfTests/OWNERS new file mode 100644 index 000000000000..72c0a9e6e90c --- /dev/null +++ b/tests/ActivityManagerPerfTests/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/am/OWNERS diff --git a/tests/AmSlam/OWNERS b/tests/AmSlam/OWNERS new file mode 100644 index 000000000000..72c0a9e6e90c --- /dev/null +++ b/tests/AmSlam/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/am/OWNERS diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java index 7d826f7172da..e05816eb391f 100644 --- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java +++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java @@ -264,9 +264,9 @@ public final class BackgroundDexOptServiceIntegrationTests { // Set time to future. setTimeFutureDays(deltaDays); - // Set filter to quicken. - compilePackageWithFilter(PACKAGE_NAME, "quicken"); - Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME)); + // Set filter to verify. + compilePackageWithFilter(PACKAGE_NAME, "verify"); + Assert.assertEquals("verify", getCompilerFilter(PACKAGE_NAME)); // Fill up storage to trigger low storage threshold. fillUpToLowStorage(); @@ -290,9 +290,9 @@ public final class BackgroundDexOptServiceIntegrationTests { // Set time to future. setTimeFutureDays(deltaDays); - // Set filter to quicken. - compilePackageWithFilter(PACKAGE_NAME, "quicken"); - Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME)); + // Set filter to speed-profile. + compilePackageWithFilter(PACKAGE_NAME, "speed-profile"); + Assert.assertEquals("speed-profile", getCompilerFilter(PACKAGE_NAME)); // Fill up storage to trigger low storage threshold. fillUpToLowStorage(); diff --git a/tests/BlobStoreTestUtils/OWNERS b/tests/BlobStoreTestUtils/OWNERS new file mode 100644 index 000000000000..65bb6b8a5423 --- /dev/null +++ b/tests/BlobStoreTestUtils/OWNERS @@ -0,0 +1 @@ +include /apex/blobstore/OWNERS diff --git a/tests/Camera2Tests/OWNERS b/tests/Camera2Tests/OWNERS new file mode 100644 index 000000000000..f48a95c5b3a3 --- /dev/null +++ b/tests/Camera2Tests/OWNERS @@ -0,0 +1 @@ +include platform/frameworks/av:/camera/OWNERS diff --git a/tests/CanvasCompare/OWNERS b/tests/CanvasCompare/OWNERS new file mode 100644 index 000000000000..c88a9f82c347 --- /dev/null +++ b/tests/CanvasCompare/OWNERS @@ -0,0 +1 @@ +include /libs/hwui/OWNERS diff --git a/tests/Compatibility/OWNERS b/tests/Compatibility/OWNERS new file mode 100644 index 000000000000..f8c3520e9fa8 --- /dev/null +++ b/tests/Compatibility/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/compat/OWNERS diff --git a/tests/DozeTest/OWNERS b/tests/DozeTest/OWNERS new file mode 100644 index 000000000000..2e96c97c8bb3 --- /dev/null +++ b/tests/DozeTest/OWNERS @@ -0,0 +1 @@ +include /packages/SystemUI/OWNERS diff --git a/tests/FixVibrateSetting/OWNERS b/tests/FixVibrateSetting/OWNERS new file mode 100644 index 000000000000..cc63ceb2c7ad --- /dev/null +++ b/tests/FixVibrateSetting/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/vibrator/OWNERS diff --git a/tests/FlickerTests/OWNERS b/tests/FlickerTests/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/tests/FlickerTests/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt index 7b5dc872a5a2..7bd96f574ee2 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt @@ -16,6 +16,7 @@ package com.android.server.wm.flicker.ime +import androidx.test.filters.FlakyTest import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry @@ -42,6 +43,7 @@ import org.junit.runners.Parameterized @RequiresDevice @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@FlakyTest(bugId = 175027130) class ReOpenImeWindowTest( testName: String, flickerSpec: Flicker diff --git a/tests/HugeBackup/OWNERS b/tests/HugeBackup/OWNERS new file mode 100644 index 000000000000..d99779e3d9da --- /dev/null +++ b/tests/HugeBackup/OWNERS @@ -0,0 +1 @@ +include /services/backup/OWNERS diff --git a/tests/HwAccelerationTest/OWNERS b/tests/HwAccelerationTest/OWNERS new file mode 100644 index 000000000000..c88a9f82c347 --- /dev/null +++ b/tests/HwAccelerationTest/OWNERS @@ -0,0 +1 @@ +include /libs/hwui/OWNERS diff --git a/tests/Input/OWNERS b/tests/Input/OWNERS new file mode 100644 index 000000000000..d701f23cb9b8 --- /dev/null +++ b/tests/Input/OWNERS @@ -0,0 +1 @@ +include /core/java/android/hardware/input/OWNERS diff --git a/tests/JobSchedulerPerfTests/OWNERS b/tests/JobSchedulerPerfTests/OWNERS new file mode 100644 index 000000000000..6f207fb1a00e --- /dev/null +++ b/tests/JobSchedulerPerfTests/OWNERS @@ -0,0 +1 @@ +include /apex/jobscheduler/OWNERS diff --git a/tests/JobSchedulerTestApp/OWNERS b/tests/JobSchedulerTestApp/OWNERS new file mode 100644 index 000000000000..6f207fb1a00e --- /dev/null +++ b/tests/JobSchedulerTestApp/OWNERS @@ -0,0 +1 @@ +include /apex/jobscheduler/OWNERS diff --git a/tests/LocationTracker/OWNERS b/tests/LocationTracker/OWNERS new file mode 100644 index 000000000000..5ac6028411f0 --- /dev/null +++ b/tests/LocationTracker/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/location/OWNERS diff --git a/tests/LowStorageTest/OWNERS b/tests/LowStorageTest/OWNERS new file mode 100644 index 000000000000..6f9dbea36b06 --- /dev/null +++ b/tests/LowStorageTest/OWNERS @@ -0,0 +1 @@ +include /core/java/android/os/storage/OWNERS diff --git a/tests/NetworkSecurityConfigTest/OWNERS b/tests/NetworkSecurityConfigTest/OWNERS new file mode 100644 index 000000000000..aa87958f1d53 --- /dev/null +++ b/tests/NetworkSecurityConfigTest/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/net/OWNERS diff --git a/tests/PackageWatchdog/OWNERS b/tests/PackageWatchdog/OWNERS new file mode 100644 index 000000000000..d04a70619caa --- /dev/null +++ b/tests/PackageWatchdog/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/rollback/OWNERS diff --git a/tests/PackageWatchdog/src/com/android/server/OWNERS b/tests/PackageWatchdog/src/com/android/server/OWNERS new file mode 100644 index 000000000000..5cf4dcf92048 --- /dev/null +++ b/tests/PackageWatchdog/src/com/android/server/OWNERS @@ -0,0 +1 @@ +per-file PackageWatchdogTest.java = file:/services/core/java/com/android/server/rollback/OWNERS diff --git a/tests/PlatformCompatGating/OWNERS b/tests/PlatformCompatGating/OWNERS new file mode 100644 index 000000000000..f8c3520e9fa8 --- /dev/null +++ b/tests/PlatformCompatGating/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/compat/OWNERS diff --git a/tests/RollbackTest/OWNERS b/tests/RollbackTest/OWNERS new file mode 100644 index 000000000000..d04a70619caa --- /dev/null +++ b/tests/RollbackTest/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/rollback/OWNERS diff --git a/tests/SoundTriggerTestApp/OWNERS b/tests/SoundTriggerTestApp/OWNERS new file mode 100644 index 000000000000..816bc6bba639 --- /dev/null +++ b/tests/SoundTriggerTestApp/OWNERS @@ -0,0 +1 @@ +include /core/java/android/media/soundtrigger/OWNERS diff --git a/tests/SoundTriggerTests/OWNERS b/tests/SoundTriggerTests/OWNERS new file mode 100644 index 000000000000..816bc6bba639 --- /dev/null +++ b/tests/SoundTriggerTests/OWNERS @@ -0,0 +1 @@ +include /core/java/android/media/soundtrigger/OWNERS diff --git a/tests/StagedInstallTest/OWNERS b/tests/StagedInstallTest/OWNERS new file mode 100644 index 000000000000..d825dfd7cf00 --- /dev/null +++ b/tests/StagedInstallTest/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pm/OWNERS diff --git a/tests/StatusBar/OWNERS b/tests/StatusBar/OWNERS new file mode 100644 index 000000000000..2e96c97c8bb3 --- /dev/null +++ b/tests/StatusBar/OWNERS @@ -0,0 +1 @@ +include /packages/SystemUI/OWNERS diff --git a/tests/TaskOrganizerTest/OWNERS b/tests/TaskOrganizerTest/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/tests/TaskOrganizerTest/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/tests/TelephonyCommonTests/OWNERS b/tests/TelephonyCommonTests/OWNERS new file mode 100644 index 000000000000..640baf2297b4 --- /dev/null +++ b/tests/TelephonyCommonTests/OWNERS @@ -0,0 +1 @@ +include /telephony/OWNERS diff --git a/tests/UsageReportingTest/OWNERS b/tests/UsageReportingTest/OWNERS new file mode 100644 index 000000000000..d3227de87684 --- /dev/null +++ b/tests/UsageReportingTest/OWNERS @@ -0,0 +1 @@ +include /services/usage/OWNERS diff --git a/tests/UsageStatsPerfTests/OWNERS b/tests/UsageStatsPerfTests/OWNERS new file mode 100644 index 000000000000..d3227de87684 --- /dev/null +++ b/tests/UsageStatsPerfTests/OWNERS @@ -0,0 +1 @@ +include /services/usage/OWNERS diff --git a/tests/UsageStatsTest/OWNERS b/tests/UsageStatsTest/OWNERS new file mode 100644 index 000000000000..d3227de87684 --- /dev/null +++ b/tests/UsageStatsTest/OWNERS @@ -0,0 +1 @@ +include /services/usage/OWNERS diff --git a/tests/UsbHostExternalManagmentTest/OWNERS b/tests/UsbHostExternalManagmentTest/OWNERS new file mode 100644 index 000000000000..f7b2a37a297a --- /dev/null +++ b/tests/UsbHostExternalManagmentTest/OWNERS @@ -0,0 +1 @@ +include /services/usb/OWNERS diff --git a/tests/UsbManagerTests/OWNERS b/tests/UsbManagerTests/OWNERS new file mode 100644 index 000000000000..f7b2a37a297a --- /dev/null +++ b/tests/UsbManagerTests/OWNERS @@ -0,0 +1 @@ +include /services/usb/OWNERS diff --git a/tests/UsbTests/OWNERS b/tests/UsbTests/OWNERS new file mode 100644 index 000000000000..f7b2a37a297a --- /dev/null +++ b/tests/UsbTests/OWNERS @@ -0,0 +1 @@ +include /services/usb/OWNERS diff --git a/tests/VoiceInteraction/OWNERS b/tests/VoiceInteraction/OWNERS new file mode 100644 index 000000000000..ef1061b28b63 --- /dev/null +++ b/tests/VoiceInteraction/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/voice/OWNERS diff --git a/tests/WindowAnimationJank/OWNERS b/tests/WindowAnimationJank/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/tests/WindowAnimationJank/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/tests/WindowInsetsTests/OWNERS b/tests/WindowInsetsTests/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/tests/WindowInsetsTests/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/tests/backup/OWNERS b/tests/backup/OWNERS new file mode 100644 index 000000000000..d99779e3d9da --- /dev/null +++ b/tests/backup/OWNERS @@ -0,0 +1 @@ +include /services/backup/OWNERS diff --git a/tests/benchmarks/src/com/android/server/net/OWNERS b/tests/benchmarks/src/com/android/server/net/OWNERS new file mode 100644 index 000000000000..aa87958f1d53 --- /dev/null +++ b/tests/benchmarks/src/com/android/server/net/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/net/OWNERS diff --git a/tests/net/common/java/android/net/LinkAddressTest.java b/tests/net/common/java/android/net/LinkAddressTest.java index 60308e32b88d..1eaf30c5e068 100644 --- a/tests/net/common/java/android/net/LinkAddressTest.java +++ b/tests/net/common/java/android/net/LinkAddressTest.java @@ -68,8 +68,8 @@ public class LinkAddressTest { private static final String V4 = "192.0.2.1"; private static final String V6 = "2001:db8::1"; - private static final InetAddress V4_ADDRESS = NetworkUtils.numericToInetAddress(V4); - private static final InetAddress V6_ADDRESS = NetworkUtils.numericToInetAddress(V6); + private static final InetAddress V4_ADDRESS = InetAddresses.parseNumericAddress(V4); + private static final InetAddress V6_ADDRESS = InetAddresses.parseNumericAddress(V6); @Test public void testConstants() { @@ -131,10 +131,10 @@ public class LinkAddressTest { ipv6Loopback = new LinkAddress(addrs.get(0)); } - assertEquals(NetworkUtils.numericToInetAddress("127.0.0.1"), ipv4Loopback.getAddress()); + assertEquals(InetAddresses.parseNumericAddress("127.0.0.1"), ipv4Loopback.getAddress()); assertEquals(8, ipv4Loopback.getPrefixLength()); - assertEquals(NetworkUtils.numericToInetAddress("::1"), ipv6Loopback.getAddress()); + assertEquals(InetAddresses.parseNumericAddress("::1"), ipv6Loopback.getAddress()); assertEquals(128, ipv6Loopback.getPrefixLength()); // Null addresses are rejected. diff --git a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java index 835a83e9ddc7..c5b25bdcac48 100644 --- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java +++ b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java @@ -147,5 +147,11 @@ public final class TcpKeepalivePacketDataTest { assertEquals(resultData.rcvWndScale, wndScale); assertEquals(resultData.tos, tos); assertEquals(resultData.ttl, ttl); + + final String expected = "" + + "android.net.TcpKeepalivePacketDataParcelable{srcAddress: [10, 0, 0, 1]," + + " srcPort: 1234, dstAddress: [10, 0, 0, 5], dstPort: 4321, seq: 286331153," + + " ack: 572662306, rcvWnd: 48000, rcvWndScale: 2, tos: 4, ttl: 64}"; + assertEquals(expected, resultData.toString()); } } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 5d4573716145..5bfcd5202cbf 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -181,7 +181,6 @@ import android.net.NetworkStack; import android.net.NetworkStackClient; import android.net.NetworkState; import android.net.NetworkTestResultParcelable; -import android.net.NetworkUtils; import android.net.ProxyInfo; import android.net.ResolverParamsParcel; import android.net.RouteInfo; @@ -1958,6 +1957,37 @@ public class ConnectivityServiceTest { } @Test + public void testOwnerUidCannotChange() throws Exception { + // Owner UIDs are not visible without location permission. + setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION); + + final NetworkCapabilities ncTemplate = new NetworkCapabilities(); + final int originalOwnerUid = Process.myUid(); + ncTemplate.setOwnerUid(originalOwnerUid); + + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), + ncTemplate); + mWiFiNetworkAgent.connect(false); + waitForIdle(); + + // Send ConnectivityService an update to the mWiFiNetworkAgent's capabilities that changes + // the owner UID and an unrelated capability. + NetworkCapabilities agentCapabilities = mWiFiNetworkAgent.getNetworkCapabilities(); + assertEquals(originalOwnerUid, agentCapabilities.getOwnerUid()); + agentCapabilities.setOwnerUid(42); + assertFalse(agentCapabilities.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); + agentCapabilities.addCapability(NET_CAPABILITY_NOT_CONGESTED); + mWiFiNetworkAgent.setNetworkCapabilities(agentCapabilities, true); + waitForIdle(); + + // Check that the capability change has been applied but the owner UID is not modified. + NetworkCapabilities nc = mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()); + assertEquals(originalOwnerUid, nc.getOwnerUid()); + assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); + } + + @Test public void testMultipleLingering() throws Exception { // This test would be flaky with the default 120ms timer: that is short enough that // lingered networks are torn down before assertions can be run. We don't want to mock the @@ -4790,7 +4820,7 @@ public class ConnectivityServiceTest { lp.setInterfaceName(WIFI_IFNAME); LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24"); RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null, - NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName()); + InetAddresses.parseNumericAddress("192.168.12.1"), lp.getInterfaceName()); lp.addLinkAddress(myIpv4Address); lp.addRoute(myIpv4DefaultRoute); diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java index 529d03c520ba..799bcc82d2a9 100644 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java @@ -34,6 +34,7 @@ import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; import android.net.INetd; +import android.net.InetAddresses; import android.net.IpSecAlgorithm; import android.net.IpSecConfig; import android.net.IpSecManager; @@ -44,7 +45,6 @@ import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecUdpEncapResponse; import android.net.LinkAddress; import android.net.Network; -import android.net.NetworkUtils; import android.os.Binder; import android.os.INetworkManagementService; import android.os.ParcelFileDescriptor; @@ -272,7 +272,7 @@ public class IpSecServiceParameterizedTest { IpSecSpiResponse spi = mIpSecService.allocateSecurityParameterIndex( - NetworkUtils.numericToInetAddress(remoteAddress).getHostAddress(), + InetAddresses.parseNumericAddress(remoteAddress).getHostAddress(), IpSecManager.INVALID_SECURITY_PARAMETER_INDEX, new Binder()); return spi.resourceId; diff --git a/tests/notification/OWNERS b/tests/notification/OWNERS new file mode 100644 index 000000000000..396fd1213aca --- /dev/null +++ b/tests/notification/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/notification/OWNERS diff --git a/tests/permission/OWNERS b/tests/permission/OWNERS new file mode 100644 index 000000000000..999ea0e62a0a --- /dev/null +++ b/tests/permission/OWNERS @@ -0,0 +1 @@ +include /core/java/android/permission/OWNERS diff --git a/tests/utils/DummyIME/OWNERS b/tests/utils/DummyIME/OWNERS new file mode 100644 index 000000000000..5deb2ce8f24b --- /dev/null +++ b/tests/utils/DummyIME/OWNERS @@ -0,0 +1 @@ +include /core/java/android/view/inputmethod/OWNERS diff --git a/tests/utils/StubIME/OWNERS b/tests/utils/StubIME/OWNERS new file mode 100644 index 000000000000..5deb2ce8f24b --- /dev/null +++ b/tests/utils/StubIME/OWNERS @@ -0,0 +1 @@ +include /core/java/android/view/inputmethod/OWNERS diff --git a/tests/utils/hostutils/src/com/android/tests/rollback/OWNERS b/tests/utils/hostutils/src/com/android/tests/rollback/OWNERS new file mode 100644 index 000000000000..d04a70619caa --- /dev/null +++ b/tests/utils/hostutils/src/com/android/tests/rollback/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/rollback/OWNERS diff --git a/tests/utils/testutils/java/com/android/server/accessibility/OWNERS b/tests/utils/testutils/java/com/android/server/accessibility/OWNERS new file mode 100644 index 000000000000..b74281edbf52 --- /dev/null +++ b/tests/utils/testutils/java/com/android/server/accessibility/OWNERS @@ -0,0 +1 @@ +include /core/java/android/view/accessibility/OWNERS diff --git a/tests/utils/testutils/java/com/android/server/wm/OWNERS b/tests/utils/testutils/java/com/android/server/wm/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/tests/utils/testutils/java/com/android/server/wm/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/tools/aapt/OWNERS b/tools/aapt/OWNERS new file mode 100644 index 000000000000..c232ccd457a7 --- /dev/null +++ b/tools/aapt/OWNERS @@ -0,0 +1 @@ +include /tools/aapt2/OWNERS diff --git a/tools/fonts/OWNERS b/tools/fonts/OWNERS new file mode 100644 index 000000000000..a538331dd3f4 --- /dev/null +++ b/tools/fonts/OWNERS @@ -0,0 +1 @@ +include /core/java/android/graphics/fonts/OWNERS diff --git a/tools/incident_report/OWNERS b/tools/incident_report/OWNERS new file mode 100644 index 000000000000..f76611555dbb --- /dev/null +++ b/tools/incident_report/OWNERS @@ -0,0 +1 @@ +include /cmds/incidentd/OWNERS diff --git a/tools/incident_section_gen/OWNERS b/tools/incident_section_gen/OWNERS new file mode 100644 index 000000000000..f76611555dbb --- /dev/null +++ b/tools/incident_section_gen/OWNERS @@ -0,0 +1 @@ +include /cmds/incidentd/OWNERS diff --git a/tools/powerstats/OWNERS b/tools/powerstats/OWNERS new file mode 100644 index 000000000000..d68066bb8c40 --- /dev/null +++ b/tools/powerstats/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/power/OWNERS diff --git a/tools/stats_log_api_gen/OWNERS b/tools/stats_log_api_gen/OWNERS new file mode 100644 index 000000000000..41a0c95f13c9 --- /dev/null +++ b/tools/stats_log_api_gen/OWNERS @@ -0,0 +1 @@ +yro@google.com diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java index 226d1a368223..1bb9ebccb01a 100644 --- a/wifi/java/android/net/wifi/SoftApConfiguration.java +++ b/wifi/java/android/net/wifi/SoftApConfiguration.java @@ -538,15 +538,6 @@ public final class SoftApConfiguration implements Parcelable { if (!SdkLevel.isAtLeastS()) { throw new UnsupportedOperationException(); } - return getChannelsInternal(); - } - - /** - * Internal version bypassing SdkLevel checks - * TODO(b/173791707): find a better way to allow Wifi to call its own new S APIs. - * @hide - */ - public @NonNull SparseIntArray getChannelsInternal() { return mChannels.clone(); } @@ -945,6 +936,9 @@ public final class SoftApConfiguration implements Parcelable { */ @NonNull public Builder setBands(@NonNull int[] bands) { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } if (bands.length == 0 || bands.length > 2) { throw new IllegalArgumentException("Unsupported number of bands(" + bands.length + ") configured"); @@ -1036,6 +1030,9 @@ public final class SoftApConfiguration implements Parcelable { */ @NonNull public Builder setChannels(@NonNull SparseIntArray channels) { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } if (channels.size() == 0 || channels.size() > 2) { throw new IllegalArgumentException("Unsupported number of channels(" + channels.size() + ") configured"); diff --git a/wifi/java/android/net/wifi/SoftApInfo.java b/wifi/java/android/net/wifi/SoftApInfo.java index 55c2f1759952..9a16facfec26 100644 --- a/wifi/java/android/net/wifi/SoftApInfo.java +++ b/wifi/java/android/net/wifi/SoftApInfo.java @@ -183,15 +183,6 @@ public final class SoftApInfo implements Parcelable { if (!SdkLevel.isAtLeastS()) { throw new UnsupportedOperationException(); } - return getWifiStandardInternal(); - } - - /** - * Internal version bypassing SdkLevel checks - * TODO(b/173791707): find a better way to allow Wifi to call its own new S APIs. - * @hide - */ - public @WifiAnnotations.WifiStandard int getWifiStandardInternal() { return mWifiStandard; } diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 85b3170d59bd..271a73943425 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -1638,6 +1638,11 @@ public class WifiConfiguration implements Parcelable { private String mConnectChoice; /** + * The RSSI when the user made the connectChoice. + */ + private int mConnectChoiceRssi; + + /** * Used to cache the temporary candidate during the network selection procedure. It will be * kept updating once a new scan result has a higher score than current one */ @@ -1748,6 +1753,23 @@ public class WifiConfiguration implements Parcelable { mConnectChoice = newConnectChoice; } + /** + * Associate a RSSI with the user connect choice network. + * @param rssi signal strength + * @hide + */ + public void setConnectChoiceRssi(int rssi) { + mConnectChoiceRssi = rssi; + } + + /** + * @return returns the RSSI of the last time the user made the connect choice. + * @hide + */ + public int getConnectChoiceRssi() { + return mConnectChoiceRssi; + } + /** Get the current Quality network selection status as a String (for debugging). */ @NonNull public String getNetworkStatusString() { @@ -2051,6 +2073,7 @@ public class WifiConfiguration implements Parcelable { setCandidate(source.getCandidate()); setCandidateScore(source.getCandidateScore()); setConnectChoice(source.getConnectChoice()); + setConnectChoiceRssi(source.getConnectChoiceRssi()); setHasEverConnected(source.hasEverConnected()); setHasNeverDetectedCaptivePortal(source.hasNeverDetectedCaptivePortal()); } @@ -2068,6 +2091,7 @@ public class WifiConfiguration implements Parcelable { if (getConnectChoice() != null) { dest.writeInt(CONNECT_CHOICE_EXISTS); dest.writeString(getConnectChoice()); + dest.writeInt(getConnectChoiceRssi()); } else { dest.writeInt(CONNECT_CHOICE_NOT_EXISTS); } @@ -2087,6 +2111,7 @@ public class WifiConfiguration implements Parcelable { setNetworkSelectionBSSID(in.readString()); if (in.readInt() == CONNECT_CHOICE_EXISTS) { setConnectChoice(in.readString()); + setConnectChoiceRssi(in.readInt()); } else { setConnectChoice(null); } @@ -2398,6 +2423,8 @@ public class WifiConfiguration implements Parcelable { } if (mNetworkSelectionStatus.getConnectChoice() != null) { sbuf.append(" connect choice: ").append(mNetworkSelectionStatus.getConnectChoice()); + sbuf.append(" connect choice rssi: ") + .append(mNetworkSelectionStatus.getConnectChoiceRssi()); } sbuf.append(" hasEverConnected: ") .append(mNetworkSelectionStatus.hasEverConnected()).append("\n"); diff --git a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java index ad0fdd3bce26..bcfdf7d80061 100644 --- a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java +++ b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; import android.net.MacAddress; import android.os.Parcel; @@ -371,6 +372,7 @@ public class SoftApConfigurationTest { @Test public void testDualBands() { + assumeTrue(SdkLevel.isAtLeastS()); int[] dual_bands = new int[2]; dual_bands[0] = SoftApConfiguration.BAND_2GHZ; dual_bands[1] = SoftApConfiguration.BAND_5GHZ; @@ -384,6 +386,7 @@ public class SoftApConfigurationTest { @Test public void testDualChannels() { + assumeTrue(SdkLevel.isAtLeastS()); int[] expected_dual_bands = new int[2]; expected_dual_bands[0] = SoftApConfiguration.BAND_2GHZ; expected_dual_bands[1] = SoftApConfiguration.BAND_5GHZ; @@ -417,6 +420,7 @@ public class SoftApConfigurationTest { @Test public void testInvalidBandWhenSetBands() { + assumeTrue(SdkLevel.isAtLeastS()); boolean isIllegalArgumentExceptionHappened = false; int[] dual_bands = new int[2]; dual_bands[0] = SoftApConfiguration.BAND_2GHZ; @@ -457,6 +461,7 @@ public class SoftApConfigurationTest { @Test public void testInvalidConfigWhenSetChannels() { + assumeTrue(SdkLevel.isAtLeastS()); boolean isIllegalArgumentExceptionHappened = false; SparseIntArray invalid_channels = new SparseIntArray(); try { |