diff options
451 files changed, 10609 insertions, 4713 deletions
diff --git a/Android.bp b/Android.bp index 40757a952eda..948b0a068215 100644 --- a/Android.bp +++ b/Android.bp @@ -546,6 +546,7 @@ java_library { "core/java/android/webkit/EventLogTags.logtags", "core/java/com/android/internal/logging/EventLogTags.logtags", "core/java/com/android/server/DropboxLogTags.logtags", + "core/java/org/chromium/arc/EventLogTags.logtags", ":framework-statslog-gen", ], diff --git a/Android.mk b/Android.mk index 9676958605dd..ec5fb841131e 100644 --- a/Android.mk +++ b/Android.mk @@ -276,8 +276,8 @@ non_base_dirs := \ framework_base_android_test_mock_src_files := \ $(call all-java-files-under, test-mock/src/android/test/mock) -framework_base_android_test_runner_excluding_mock_src_files := \ - $(filter-out $(framework_base_android_test_mock_src_files), $(call all-java-files-under, test-runner/src)) +framework_base_android_test_runner_src_files := \ + $(call all-java-files-under, test-runner/src) # Find all files in specific directories (relative to frameworks/base) # to document and check apis @@ -307,7 +307,6 @@ files_to_check_apis_generated := \ files_to_document := \ $(files_to_check_apis) \ $(call find-other-java-files,\ - $(addprefix ../../, $(FRAMEWORKS_DATA_BINDING_JAVA_SRC_DIRS)) \ test-runner/src) # These are relative to frameworks/base @@ -328,7 +327,7 @@ framework_docs_LOCAL_SRC_FILES := \ # These are relative to frameworks/base framework_docs_LOCAL_API_CHECK_SRC_FILES := \ $(framework_base_android_test_mock_src_files) \ - $(framework_base_android_test_runner_excluding_mock_src_files) \ + $(framework_base_android_test_runner_src_files) \ $(files_to_check_apis) \ $(common_src_files) \ diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java index 92ee7ccfc294..5653a039a9ed 100644 --- a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java +++ b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java @@ -16,6 +16,8 @@ package android.text; +import static android.text.TextDirectionHeuristics.LTR; + import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; @@ -182,4 +184,84 @@ public class StaticLayoutPerfTest { .build(); } } + + @Test + public void testCreate_MeasuredText_NoStyled_Greedy_NoHyphenation() { + final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + state.pauseTiming(); + final PremeasuredText text = PremeasuredText.build( + generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, LTR); + state.resumeTiming(); + + StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) + .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) + .build(); + } + } + + @Test + public void testCreate_MeasuredText_NoStyled_Greedy_Hyphenation() { + final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + state.pauseTiming(); + final PremeasuredText text = PremeasuredText.build( + generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, LTR); + state.resumeTiming(); + + StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) + .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) + .build(); + } + } + + @Test + public void testCreate_MeasuredText_NoStyled_Balanced_NoHyphenation() { + final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + state.pauseTiming(); + final PremeasuredText text = PremeasuredText.build( + generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, LTR); + state.resumeTiming(); + + StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) + .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) + .build(); + } + } + + @Test + public void testCreate_MeasuredText_NoStyled_Balanced_Hyphenation() { + final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + state.pauseTiming(); + final PremeasuredText text = PremeasuredText.build( + generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, LTR); + state.resumeTiming(); + + StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) + .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) + .build(); + } + } + + @Test + public void testCreate_MeasuredText_Styled_Greedy_NoHyphenation() { + final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + state.pauseTiming(); + final PremeasuredText text = PremeasuredText.build( + generateRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT, LTR); + state.resumeTiming(); + + StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) + .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) + .build(); + } + } } diff --git a/api/current.txt b/api/current.txt index d920321a9b75..321135bb825b 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6344,6 +6344,7 @@ package android.app.admin { method public java.util.List<java.lang.String> getDelegatedScopes(android.content.ComponentName, java.lang.String); method public java.lang.CharSequence getDeviceOwnerLockScreenInfo(); method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName); + method public java.util.List<java.lang.String> getKeepUninstalledPackages(android.content.ComponentName); method public int getKeyguardDisabledFeatures(android.content.ComponentName); method public int getLockTaskFeatures(android.content.ComponentName); method public java.lang.String[] getLockTaskPackages(android.content.ComponentName); @@ -6384,6 +6385,7 @@ package android.app.admin { method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]); method public boolean hasGrantedPolicy(android.content.ComponentName, int); method public boolean installCaCert(android.content.ComponentName, byte[]); + method public boolean installExistingPackage(android.content.ComponentName, java.lang.String); method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String); method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], java.lang.String, boolean); method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], java.lang.String, boolean, boolean); @@ -6393,8 +6395,9 @@ package android.app.admin { method public boolean isBackupServiceEnabled(android.content.ComponentName); method public deprecated boolean isCallerApplicationRestrictionsManagingPackage(); method public boolean isDeviceOwnerApp(java.lang.String); + method public boolean isEphemeralUser(android.content.ComponentName); method public boolean isLockTaskPermitted(java.lang.String); - method public boolean isLogoutButtonEnabled(); + method public boolean isLogoutEnabled(); method public boolean isManagedProfile(android.content.ComponentName); method public boolean isMasterVolumeMuted(android.content.ComponentName); method public boolean isNetworkLoggingEnabled(android.content.ComponentName); @@ -6434,11 +6437,12 @@ package android.app.admin { method public void setDelegatedScopes(android.content.ComponentName, java.lang.String, java.util.List<java.lang.String>); method public void setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.CharSequence); method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String); + method public void setKeepUninstalledPackages(android.content.ComponentName, java.util.List<java.lang.String>); method public boolean setKeyguardDisabled(android.content.ComponentName, boolean); method public void setKeyguardDisabledFeatures(android.content.ComponentName, int); method public void setLockTaskFeatures(android.content.ComponentName, int); method public void setLockTaskPackages(android.content.ComponentName, java.lang.String[]) throws java.lang.SecurityException; - method public void setLogoutButtonEnabled(android.content.ComponentName, boolean); + method public void setLogoutEnabled(android.content.ComponentName, boolean); method public void setLongSupportMessage(android.content.ComponentName, java.lang.CharSequence); method public void setMasterVolumeMuted(android.content.ComponentName, boolean); method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int); @@ -6503,6 +6507,8 @@ package android.app.admin { field public static final java.lang.String DELEGATION_BLOCK_UNINSTALL = "delegation-block-uninstall"; field public static final java.lang.String DELEGATION_CERT_INSTALL = "delegation-cert-install"; field public static final java.lang.String DELEGATION_ENABLE_SYSTEM_APP = "delegation-enable-system-app"; + field public static final java.lang.String DELEGATION_INSTALL_EXISTING_PACKAGE = "delegation-install-existing-package"; + field public static final java.lang.String DELEGATION_KEEP_UNINSTALLED_PACKAGES = "delegation-keep-uninstalled-packages"; field public static final java.lang.String DELEGATION_PACKAGE_ACCESS = "delegation-package-access"; field public static final java.lang.String DELEGATION_PERMISSION_GRANT = "delegation-permission-grant"; field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2 @@ -6556,6 +6562,7 @@ package android.app.admin { field public static final int KEYGUARD_DISABLE_TRUST_AGENTS = 16; // 0x10 field public static final int KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS = 8; // 0x8 field public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 1; // 0x1 + field public static final int LEAVE_ALL_SYSTEM_APPS_ENABLED = 16; // 0x10 field public static final int LOCK_TASK_FEATURE_GLOBAL_ACTIONS = 16; // 0x10 field public static final int LOCK_TASK_FEATURE_HOME = 4; // 0x4 field public static final int LOCK_TASK_FEATURE_KEYGUARD = 32; // 0x20 @@ -7006,11 +7013,14 @@ package android.app.slice { field public static final java.lang.String HINT_LARGE = "large"; field public static final java.lang.String HINT_LIST = "list"; field public static final java.lang.String HINT_LIST_ITEM = "list_item"; + field public static final java.lang.String HINT_MAX = "max"; field public static final java.lang.String HINT_NO_TINT = "no_tint"; field public static final java.lang.String HINT_PARTIAL = "partial"; field public static final java.lang.String HINT_SELECTED = "selected"; field public static final java.lang.String HINT_TITLE = "title"; + field public static final java.lang.String SUBTYPE_COLOR = "color"; field public static final java.lang.String SUBTYPE_MESSAGE = "message"; + field public static final java.lang.String SUBTYPE_SLIDER = "slider"; field public static final java.lang.String SUBTYPE_SOURCE = "source"; } @@ -7019,12 +7029,16 @@ package android.app.slice { ctor public Slice.Builder(android.app.slice.Slice.Builder); method public android.app.slice.Slice.Builder addAction(android.app.PendingIntent, android.app.slice.Slice); method public android.app.slice.Slice.Builder addAction(android.app.PendingIntent, android.app.slice.Slice, java.lang.String); - method public android.app.slice.Slice.Builder addColor(int, java.lang.String, java.lang.String...); - method public android.app.slice.Slice.Builder addColor(int, java.lang.String, java.util.List<java.lang.String>); + method public android.app.slice.Slice.Builder addBundle(android.os.Bundle, java.lang.String, java.lang.String...); + method public android.app.slice.Slice.Builder addBundle(android.os.Bundle, java.lang.String, java.util.List<java.lang.String>); + method public deprecated android.app.slice.Slice.Builder addColor(int, java.lang.String, java.lang.String...); + method public deprecated android.app.slice.Slice.Builder addColor(int, java.lang.String, java.util.List<java.lang.String>); method public android.app.slice.Slice.Builder addHints(java.lang.String...); method public android.app.slice.Slice.Builder addHints(java.util.List<java.lang.String>); method public android.app.slice.Slice.Builder addIcon(android.graphics.drawable.Icon, java.lang.String, java.lang.String...); method public android.app.slice.Slice.Builder addIcon(android.graphics.drawable.Icon, java.lang.String, java.util.List<java.lang.String>); + method public android.app.slice.Slice.Builder addInt(int, java.lang.String, java.lang.String...); + method public android.app.slice.Slice.Builder addInt(int, java.lang.String, java.util.List<java.lang.String>); method public android.app.slice.Slice.Builder addRemoteInput(android.app.RemoteInput, java.lang.String, java.util.List<java.lang.String>); method public android.app.slice.Slice.Builder addRemoteInput(android.app.RemoteInput, java.lang.String, java.lang.String...); method public android.app.slice.Slice.Builder addSubSlice(android.app.slice.Slice); @@ -7040,10 +7054,12 @@ package android.app.slice { public final class SliceItem implements android.os.Parcelable { method public int describeContents(); method public android.app.PendingIntent getAction(); - method public int getColor(); + method public android.os.Bundle getBundle(); + method public deprecated int getColor(); method public java.lang.String getFormat(); method public java.util.List<java.lang.String> getHints(); method public android.graphics.drawable.Icon getIcon(); + method public int getInt(); method public android.app.RemoteInput getRemoteInput(); method public android.app.slice.Slice getSlice(); method public java.lang.String getSubType(); @@ -7053,8 +7069,10 @@ package android.app.slice { method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.slice.SliceItem> CREATOR; field public static final java.lang.String FORMAT_ACTION = "action"; - field public static final java.lang.String FORMAT_COLOR = "color"; + field public static final java.lang.String FORMAT_BUNDLE = "bundle"; + field public static final deprecated java.lang.String FORMAT_COLOR = "color"; field public static final java.lang.String FORMAT_IMAGE = "image"; + field public static final java.lang.String FORMAT_INT = "int"; field public static final java.lang.String FORMAT_REMOTE_INPUT = "input"; field public static final java.lang.String FORMAT_SLICE = "slice"; field public static final java.lang.String FORMAT_TEXT = "text"; @@ -30950,7 +30968,9 @@ package android.os { ctor public Build.VERSION(); field public static final java.lang.String BASE_OS; field public static final java.lang.String CODENAME; + field public static final int FIRST_SDK_INT; field public static final java.lang.String INCREMENTAL; + field public static final int MIN_SUPPORTED_TARGET_SDK_INT; field public static final int PREVIEW_SDK_INT; field public static final java.lang.String RELEASE; field public static final deprecated java.lang.String SDK; @@ -40212,10 +40232,12 @@ package android.telephony { field public static final java.lang.String KEY_RCS_CONFIG_SERVER_URL_STRING = "rcs_config_server_url_string"; field public static final java.lang.String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool"; field public static final java.lang.String KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL = "restart_radio_on_pdp_fail_regular_deactivation_bool"; + field public static final java.lang.String KEY_RTT_SUPPORTED_BOOL = "rtt_supported_bool"; field public static final java.lang.String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool"; field public static final java.lang.String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool"; field public static final java.lang.String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool"; field public static final java.lang.String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool"; + field public static final java.lang.String KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL = "show_signal_strength_in_sim_status_bool"; field public static final java.lang.String KEY_SIMPLIFIED_NETWORK_SETTINGS_BOOL = "simplified_network_settings_bool"; field public static final java.lang.String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool"; field public static final java.lang.String KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL = "sms_requires_destination_number_conversion_bool"; @@ -42264,6 +42286,27 @@ package android.text { method public abstract int getSpanTypeId(); } + public class PremeasuredText implements android.text.Spanned { + method public static android.text.PremeasuredText build(java.lang.CharSequence, android.text.TextPaint, android.text.TextDirectionHeuristic); + method public static android.text.PremeasuredText build(java.lang.CharSequence, android.text.TextPaint, android.text.TextDirectionHeuristic, int, int); + method public char charAt(int); + method public int getEnd(); + method public android.text.TextPaint getPaint(); + method public int getParagraphCount(); + method public int getParagraphEnd(int); + method public int getParagraphStart(int); + method public int getSpanEnd(java.lang.Object); + method public int getSpanFlags(java.lang.Object); + method public int getSpanStart(java.lang.Object); + method public <T> T[] getSpans(int, int, java.lang.Class<T>); + method public int getStart(); + method public java.lang.CharSequence getText(); + method public android.text.TextDirectionHeuristic getTextDir(); + method public int length(); + method public int nextSpanTransition(int, int, java.lang.Class); + method public java.lang.CharSequence subSequence(int, int); + } + public class Selection { method public static boolean extendDown(android.text.Spannable, android.text.Layout); method public static boolean extendLeft(android.text.Spannable, android.text.Layout); diff --git a/api/system-current.txt b/api/system-current.txt index 33fa246a9f51..d87fcbca9f2e 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -613,7 +613,9 @@ package android.app.usage { public final class UsageStatsManager { method public int getAppStandbyBucket(java.lang.String); + method public java.util.Map<java.lang.String, java.lang.Integer> getAppStandbyBuckets(); method public void setAppStandbyBucket(java.lang.String, int); + method public void setAppStandbyBuckets(java.util.Map<java.lang.String, java.lang.Integer>); method public void whitelistAppTemporarily(java.lang.String, long, android.os.UserHandle); field public static final int STANDBY_BUCKET_EXEMPTED = 5; // 0x5 field public static final int STANDBY_BUCKET_NEVER = 50; // 0x32 @@ -4136,6 +4138,7 @@ package android.telephony { method public int getCurrentPhoneType(int); method public deprecated boolean getDataEnabled(); method public deprecated boolean getDataEnabled(int); + method public boolean getEmergencyCallbackMode(); method public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms(); method public android.os.Bundle getVisualVoicemailSettings(); method public boolean handlePinMmi(java.lang.String); diff --git a/api/test-current.txt b/api/test-current.txt index 27e585d0a828..3fc5cd6efc76 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -120,6 +120,7 @@ package android.app.usage { public class StorageStatsManager { method public boolean isQuotaSupported(java.util.UUID); + method public boolean isReservedSupported(java.util.UUID); } } diff --git a/cmds/ime/Android.mk b/cmds/ime/Android.mk index 6803fc01154c..ca608e8c2c34 100644 --- a/cmds/ime/Android.mk +++ b/cmds/ime/Android.mk @@ -3,14 +3,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES := $(call all-subdir-java-files) -LOCAL_MODULE := imelib -LOCAL_MODULE_STEM := ime -include $(BUILD_JAVA_LIBRARY) - -include $(CLEAR_VARS) LOCAL_MODULE := ime LOCAL_MODULE_CLASS := EXECUTABLES LOCAL_SRC_FILES := ime -LOCAL_REQUIRED_MODULES := imelib include $(BUILD_PREBUILT) diff --git a/cmds/ime/ime b/cmds/ime/ime index 1a1fdd96da6e..180dc761055b 100755 --- a/cmds/ime/ime +++ b/cmds/ime/ime @@ -1,8 +1,2 @@ #!/system/bin/sh -# Script to start "pm" on the device, which has a very rudimentary -# shell. -# -base=/system -export CLASSPATH=$base/framework/ime.jar -exec app_process $base/bin com.android.commands.ime.Ime "$@" - +exec cmd input_method "$@" diff --git a/cmds/ime/src/com/android/commands/ime/Ime.java b/cmds/ime/src/com/android/commands/ime/Ime.java deleted file mode 100644 index 72a0af6c2d99..000000000000 --- a/cmds/ime/src/com/android/commands/ime/Ime.java +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (C) 2007 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.commands.ime; - -import com.android.internal.view.IInputMethodManager; - -import android.os.RemoteException; -import android.os.ServiceManager; -import android.util.PrintStreamPrinter; -import android.util.Printer; -import android.view.inputmethod.InputMethodInfo; - -import java.util.List; - -public final class Ime { - IInputMethodManager mImm; - - private String[] mArgs; - private int mNextArg; - private String mCurArgData; - - private static final String IMM_NOT_RUNNING_ERR = - "Error: Could not access the Input Method Manager. Is the system running?"; - - public static void main(String[] args) { - new Ime().run(args); - } - - public void run(String[] args) { - if (args.length < 1) { - showUsage(); - return; - } - - mImm = IInputMethodManager.Stub.asInterface(ServiceManager.getService("input_method")); - if (mImm == null) { - System.err.println(IMM_NOT_RUNNING_ERR); - return; - } - - mArgs = args; - String op = args[0]; - mNextArg = 1; - - if ("list".equals(op)) { - runList(); - return; - } - - if ("enable".equals(op)) { - runSetEnabled(true); - return; - } - - if ("disable".equals(op)) { - runSetEnabled(false); - return; - } - - if ("set".equals(op)) { - runSet(); - return; - } - - if (op != null) { - System.err.println("Error: unknown command '" + op + "'"); - } - showUsage(); - } - - /** - * Execute the list sub-command. - */ - private void runList() { - String opt; - boolean all = false; - boolean brief = false; - while ((opt=nextOption()) != null) { - if (opt.equals("-a")) { - all = true; - } else if (opt.equals("-s")) { - brief = true; - } else { - System.err.println("Error: Unknown option: " + opt); - showUsage(); - return; - } - } - - - List<InputMethodInfo> methods; - if (!all) { - try { - methods = mImm.getEnabledInputMethodList(); - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(IMM_NOT_RUNNING_ERR); - return; - } - } else { - try { - methods = mImm.getInputMethodList(); - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(IMM_NOT_RUNNING_ERR); - return; - } - } - - if (methods != null) { - Printer pr = new PrintStreamPrinter(System.out); - for (int i=0; i<methods.size(); i++) { - InputMethodInfo imi = methods.get(i); - if (brief) { - System.out.println(imi.getId()); - } else { - System.out.println(imi.getId() + ":"); - imi.dump(pr, " "); - } - } - } - } - - private void runSetEnabled(boolean state) { - String id = nextArg(); - if (id == null) { - System.err.println("Error: no input method ID specified"); - showUsage(); - return; - } - - try { - boolean res = mImm.setInputMethodEnabled(id, state); - if (state) { - System.out.println("Input method " + id + ": " - + (res ? "already enabled" : "now enabled")); - } else { - System.out.println("Input method " + id + ": " - + (res ? "now disabled" : "already disabled")); - } - } catch (IllegalArgumentException e) { - System.err.println("Error: " + e.getMessage()); - return; - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(IMM_NOT_RUNNING_ERR); - return; - } - } - - private void runSet() { - String id = nextArg(); - if (id == null) { - System.err.println("Error: no input method ID specified"); - showUsage(); - return; - } - - try { - mImm.setInputMethod(null, id); - System.out.println("Input method " + id + " selected"); - } catch (IllegalArgumentException e) { - System.err.println("Error: " + e.getMessage()); - return; - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(IMM_NOT_RUNNING_ERR); - return; - } - } - - private String nextOption() { - if (mNextArg >= mArgs.length) { - return null; - } - String arg = mArgs[mNextArg]; - if (!arg.startsWith("-")) { - return null; - } - mNextArg++; - if (arg.equals("--")) { - return null; - } - if (arg.length() > 1 && arg.charAt(1) != '-') { - if (arg.length() > 2) { - mCurArgData = arg.substring(2); - return arg.substring(0, 2); - } else { - mCurArgData = null; - return arg; - } - } - mCurArgData = null; - return arg; - } - - private String nextOptionData() { - if (mCurArgData != null) { - return mCurArgData; - } - if (mNextArg >= mArgs.length) { - return null; - } - String data = mArgs[mNextArg]; - mNextArg++; - return data; - } - - private String nextArg() { - if (mNextArg >= mArgs.length) { - return null; - } - String arg = mArgs[mNextArg]; - mNextArg++; - return arg; - } - - private static void showUsage() { - System.err.println("usage: ime list [-a] [-s]"); - System.err.println(" ime enable ID"); - System.err.println(" ime disable ID"); - System.err.println(" ime set ID"); - System.err.println(""); - System.err.println("The list command prints all enabled input methods. Use"); - System.err.println("the -a option to see all input methods. Use"); - System.err.println("the -s option to see only a single summary line of each."); - System.err.println(""); - System.err.println("The enable command allows the given input method ID to be used."); - System.err.println(""); - System.err.println("The disable command disallows the given input method ID from use."); - System.err.println(""); - System.err.println("The set command switches to the given input method ID."); - } -} diff --git a/cmds/incident_helper/Android.bp b/cmds/incident_helper/Android.bp index 2ef037143f07..fc0bdccb268b 100644 --- a/cmds/incident_helper/Android.bp +++ b/cmds/incident_helper/Android.bp @@ -38,6 +38,7 @@ cc_binary { cc_test { name: "incident_helper_test", + test_suites: ["device-tests"], defaults: ["incident_helper_defaults"], local_include_dirs: ["src/"], diff --git a/cmds/incident_helper/AndroidTest.xml b/cmds/incident_helper/AndroidTest.xml new file mode 100644 index 000000000000..6d242bcf435a --- /dev/null +++ b/cmds/incident_helper/AndroidTest.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> +<configuration description="Config for incident_helper_test"> + <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"> + <option name="cleanup" value="true" /> + <option name="push" value="incident_helper_test->/data/nativetest/incident_helper_test" /> + <option name="push" value="testdata->/data/nativetest/testdata" /> + </target_preparer> + <option name="test-suite-tag" value="apct" /> + <test class="com.android.tradefed.testtype.GTest" > + <option name="native-test-device-path" value="/data/nativetest" /> + <option name="module-name" value="incident_helper_test" /> + </test> +</configuration> diff --git a/cmds/incident_helper/src/ih_util.cpp b/cmds/incident_helper/src/ih_util.cpp index db4f586c7e31..4bf956a9a03d 100644 --- a/cmds/incident_helper/src/ih_util.cpp +++ b/cmds/incident_helper/src/ih_util.cpp @@ -297,3 +297,82 @@ Table::insertField(ProtoOutputStream* proto, const std::string& name, const std: } return true; } + +// ================================================================================ +Message::Message(Table* table) + :mTable(table), + mPreviousField(""), + mTokens(), + mSubMessages() +{ +} + +Message::~Message() +{ +} + +void +Message::addSubMessage(uint64_t fieldId, Message* fieldMsg) +{ + for (auto iter = mTable->mFields.begin(); iter != mTable->mFields.end(); iter++) { + if (iter->second == fieldId) { + mSubMessages[iter->first] = fieldMsg; + return; + } + } +} + +bool +Message::insertField(ProtoOutputStream* proto, const std::string& name, const std::string& value) +{ + // If the field name can be found, it means the name is a primitive field. + if (mTable->mFields.find(name) != mTable->mFields.end()) { + endSession(proto); + // The only edge case is for example ro.hardware itself is a message, so a field called "value" + // would be defined in proto Ro::Hardware and it must be the first field. + if (mSubMessages.find(name) != mSubMessages.end()) { + startSession(proto, name); + return mSubMessages[name]->insertField(proto, "value", value); + } else { + return mTable->insertField(proto, name, value); + } + } + + // Try to find the message field which is the prefix of name, so the value would be inserted + // recursively into the submessage. + string mutableName = name; + for (auto iter = mSubMessages.begin(); iter != mSubMessages.end(); iter++) { + string fieldName = iter->first; + string prefix = fieldName + "_"; // underscore is the delimiter in the name + if (stripPrefix(&mutableName, prefix.c_str())) { + if (mPreviousField != fieldName) { + endSession(proto); + startSession(proto, fieldName); + } + return mSubMessages[fieldName]->insertField(proto, mutableName, value); + } + } + // Can't find the name in proto definition, handle it separately. + return false; +} + +void +Message::startSession(ProtoOutputStream* proto, const string& name) +{ + uint64_t fieldId = mTable->mFields[name]; + long long token = proto->start(fieldId); + mPreviousField = name; + mTokens.push(token); +} + +void +Message::endSession(ProtoOutputStream* proto) +{ + if (mPreviousField == "") return; + if (mSubMessages.find(mPreviousField) != mSubMessages.end()) { + mSubMessages[mPreviousField]->endSession(proto); + } + proto->end(mTokens.top()); + mTokens.pop(); + mPreviousField = ""; +} diff --git a/cmds/incident_helper/src/ih_util.h b/cmds/incident_helper/src/ih_util.h index 4a5fe1dd7a42..58ef29044048 100644 --- a/cmds/incident_helper/src/ih_util.h +++ b/cmds/incident_helper/src/ih_util.h @@ -18,6 +18,7 @@ #define INCIDENT_HELPER_UTIL_H #include <map> +#include <stack> #include <string> #include <vector> @@ -34,7 +35,7 @@ const std::string DEFAULT_NEWLINE = "\r\n"; const std::string TAB_DELIMITER = "\t"; const std::string COMMA_DELIMITER = ","; -// returns true if c is a-zA-Z0-9 or underscore _ +// returns true if c is a-zA-Z0-9 or underscore bool isValidChar(char c); // trim the string with the given charset @@ -102,11 +103,20 @@ private: }; /** - * The class contains a mapping between table headers to its field ids. - * And allow users to insert the field values to proto based on its header name. + * The Table class is constructed from two arrays generated by the given message with + * option (stream_proto.stream_msg).enable_fields_mapping = true. + * The names are each field's names in the message and must corresponding to the header/name of + * the text to be parsed, and the ids are the streaming proto encoded field ids. + * + * This class then allows users to insert the table values to proto based on its header. + * + * Advance feature: if some fields in the message are enums, user must explicitly add the + * mapping from enum name string to its enum values. */ +class Message; class Table { +friend class Message; public: Table(const char* names[], const uint64_t ids[], const int count); ~Table(); @@ -114,9 +124,12 @@ public: // Add enum names to values for parsing purpose. void addEnumTypeMap(const char* field, const char* enumNames[], const int enumValues[], const int enumSize); - // manually add enum names to values mapping, useful when an Enum type is used by a lot of fields, and there are no name conflicts + // Manually add enum names to values mapping, useful when an Enum type is used by + // a number of fields, there must not be any enum name conflicts. void addEnumNameToValue(const char* enumName, const int enumValue); + // Based on given name, find the right field id, parse the text value and insert to proto. + // Return false if the given name can't be found. bool insertField(ProtoOutputStream* proto, const std::string& name, const std::string& value); private: map<std::string, uint64_t> mFields; @@ -124,4 +137,47 @@ private: map<std::string, int> mEnumValuesByName; }; +/** + * Reconstructs a typical proto message given its message Table, adds submessage fields explicitly. + * It allows user to insert nested proto values purely by the names. See insertField for detail. + */ +class Message +{ +public: + Message(Table* table); + ~Message(); + + // Reconstructs the typical proto message by adding its message fields. + void addSubMessage(uint64_t fieldId, Message* fieldMsg); + + // Inserts value if the given name has the corresponding field in its message and return true. + // It will recursively search the name in submessages and find the correct field to insert. + // For example, when the name is dalvik_vm_heapsize, and the message's corresponding proto is: + // message Properties { + // message DalvikVm { + // int32 heapsize = 1; + // bool usejit = 2; + // } + // DalvikVm dalvik_vm = 1; + // string hack_in = 2; + // } + // The value will be inserted into field heapsize in dalvik_vm submessage. + // + // Also value belongs to same submessage MUST be inserted contiguously. + // For example, dalvik_vm_usejit must be inserted directly after dalvik_vm_heapsize, otherwise + // if hack_in attempts to be inserted before dalvik_vm_usejit, value of usejit isn't added as expected. + bool insertField(ProtoOutputStream* proto, const std::string& name, const std::string& value); + + // Starts a new message field proto session. + void startSession(ProtoOutputStream* proto, const string& name); + + // Ends the previous message field proto session. + void endSession(ProtoOutputStream* proto); +private: + Table* mTable; + std::string mPreviousField; + stack<long long> mTokens; + map<std::string, Message*> mSubMessages; +}; + #endif // INCIDENT_HELPER_UTIL_H diff --git a/cmds/incident_helper/src/parsers/SystemPropertiesParser.cpp b/cmds/incident_helper/src/parsers/SystemPropertiesParser.cpp index ee5feb03242e..a41ed6ebaa22 100644 --- a/cmds/incident_helper/src/parsers/SystemPropertiesParser.cpp +++ b/cmds/incident_helper/src/parsers/SystemPropertiesParser.cpp @@ -45,11 +45,119 @@ SystemPropertiesParser::Parse(const int in, const int out) const string line; string name; // the name of the property string value; // the string value of the property - ProtoOutputStream proto; - Table table(SystemPropertiesProto::_FIELD_NAMES, SystemPropertiesProto::_FIELD_IDS, SystemPropertiesProto::_FIELD_COUNT); - table.addEnumNameToValue("running", SystemPropertiesProto::STATUS_RUNNING); - table.addEnumNameToValue("stopped", SystemPropertiesProto::STATUS_STOPPED); + vector<pair<string, string>> extras; + + Table sysPropTable(SystemPropertiesProto::_FIELD_NAMES, + SystemPropertiesProto::_FIELD_IDS, + SystemPropertiesProto::_FIELD_COUNT); + Message sysProp(&sysPropTable); + + Table aaudioT(SystemPropertiesProto::Aaudio::_FIELD_NAMES, + SystemPropertiesProto::Aaudio::_FIELD_IDS, + SystemPropertiesProto::Aaudio::_FIELD_COUNT); + Message aaudio(&aaudioT); + sysProp.addSubMessage(SystemPropertiesProto::AAUDIO, &aaudio); + + Table cameraTable(SystemPropertiesProto::Camera::_FIELD_NAMES, + SystemPropertiesProto::Camera::_FIELD_IDS, + SystemPropertiesProto::Camera::_FIELD_COUNT); + Message camera(&cameraTable); + sysProp.addSubMessage(SystemPropertiesProto::CAMERA, &camera); + + Table dalvikVmTable(SystemPropertiesProto::DalvikVm::_FIELD_NAMES, + SystemPropertiesProto::DalvikVm::_FIELD_IDS, + SystemPropertiesProto::DalvikVm::_FIELD_COUNT); + Message dalvikVm(&dalvikVmTable); + sysProp.addSubMessage(SystemPropertiesProto::DALVIK_VM, &dalvikVm); + + Table initSvcTable(SystemPropertiesProto::InitSvc::_FIELD_NAMES, + SystemPropertiesProto::InitSvc::_FIELD_IDS, + SystemPropertiesProto::InitSvc::_FIELD_COUNT); + initSvcTable.addEnumNameToValue("running", SystemPropertiesProto::InitSvc::STATUS_RUNNING); + initSvcTable.addEnumNameToValue("stopped", SystemPropertiesProto::InitSvc::STATUS_STOPPED); + Message initSvc(&initSvcTable); + sysProp.addSubMessage(SystemPropertiesProto::INIT_SVC, &initSvc); + + Table logTable(SystemPropertiesProto::Log::_FIELD_NAMES, + SystemPropertiesProto::Log::_FIELD_IDS, + SystemPropertiesProto::Log::_FIELD_COUNT); + Message logMsg(&logTable); + sysProp.addSubMessage(SystemPropertiesProto::LOG, &logMsg); + + Table persistTable(SystemPropertiesProto::Persist::_FIELD_NAMES, + SystemPropertiesProto::Persist::_FIELD_IDS, + SystemPropertiesProto::Persist::_FIELD_COUNT); + Message persist(&persistTable); + sysProp.addSubMessage(SystemPropertiesProto::PERSIST, &persist); + + Table pmDexoptTable(SystemPropertiesProto::PmDexopt::_FIELD_NAMES, + SystemPropertiesProto::PmDexopt::_FIELD_IDS, + SystemPropertiesProto::PmDexopt::_FIELD_COUNT); + Message pmDexopt(&pmDexoptTable); + sysProp.addSubMessage(SystemPropertiesProto::PM_DEXOPT, &pmDexopt); + + Table roTable(SystemPropertiesProto::Ro::_FIELD_NAMES, + SystemPropertiesProto::Ro::_FIELD_IDS, + SystemPropertiesProto::Ro::_FIELD_COUNT); + Message ro(&roTable); + + Table bootTable(SystemPropertiesProto::Ro::Boot::_FIELD_NAMES, + SystemPropertiesProto::Ro::Boot::_FIELD_IDS, + SystemPropertiesProto::Ro::Boot::_FIELD_COUNT); + Message boot(&bootTable); + ro.addSubMessage(SystemPropertiesProto::Ro::BOOT, &boot); + + Table bootimageTable(SystemPropertiesProto::Ro::BootImage::_FIELD_NAMES, + SystemPropertiesProto::Ro::BootImage::_FIELD_IDS, + SystemPropertiesProto::Ro::BootImage::_FIELD_COUNT); + Message bootimage(&bootimageTable); + ro.addSubMessage(SystemPropertiesProto::Ro::BOOTIMAGE, &bootimage); + + Table buildTable(SystemPropertiesProto::Ro::Build::_FIELD_NAMES, + SystemPropertiesProto::Ro::Build::_FIELD_IDS, + SystemPropertiesProto::Ro::Build::_FIELD_COUNT); + Message build(&buildTable); + + Table versionTable(SystemPropertiesProto::Ro::Build::Version::_FIELD_NAMES, + SystemPropertiesProto::Ro::Build::Version::_FIELD_IDS, + SystemPropertiesProto::Ro::Build::Version::_FIELD_COUNT); + Message version(&versionTable); + build.addSubMessage(SystemPropertiesProto::Ro::Build::VERSION, &version); + ro.addSubMessage(SystemPropertiesProto::Ro::BUILD, &build); + + Table configTable(SystemPropertiesProto::Ro::Config::_FIELD_NAMES, + SystemPropertiesProto::Ro::Config::_FIELD_IDS, + SystemPropertiesProto::Ro::Config::_FIELD_COUNT); + Message config(&configTable); + ro.addSubMessage(SystemPropertiesProto::Ro::CONFIG, &config); + + Table hardwareTable(SystemPropertiesProto::Ro::Hardware::_FIELD_NAMES, + SystemPropertiesProto::Ro::Hardware::_FIELD_IDS, + SystemPropertiesProto::Ro::Hardware::_FIELD_COUNT); + Message hardware(&hardwareTable); + ro.addSubMessage(SystemPropertiesProto::Ro::HARDWARE, &hardware); + + Table productTable(SystemPropertiesProto::Ro::Product::_FIELD_NAMES, + SystemPropertiesProto::Ro::Product::_FIELD_IDS, + SystemPropertiesProto::Ro::Product::_FIELD_COUNT); + Message product(&productTable); + ro.addSubMessage(SystemPropertiesProto::Ro::PRODUCT, &product); + + sysProp.addSubMessage(SystemPropertiesProto::RO, &ro); + + Table sysTable(SystemPropertiesProto::Sys::_FIELD_NAMES, + SystemPropertiesProto::Sys::_FIELD_IDS, + SystemPropertiesProto::Sys::_FIELD_COUNT); + Message sys(&sysTable); + + Table usbTable(SystemPropertiesProto::Sys::Usb::_FIELD_NAMES, + SystemPropertiesProto::Sys::Usb::_FIELD_IDS, + SystemPropertiesProto::Sys::Usb::_FIELD_COUNT); + Message usb(&usbTable); + sys.addSubMessage(SystemPropertiesProto::Sys::USB, &usb); + + sysProp.addSubMessage(SystemPropertiesProto::SYS, &sys); // parse line by line while (reader.readLine(&line)) { @@ -67,13 +175,19 @@ SystemPropertiesParser::Parse(const int in, const int out) const // if the property name couldn't be found in proto definition or the value has mistype, // add to extra properties with its name and value - if (!table.insertField(&proto, convertToFieldName(name), value)) { - long long token = proto.start(SystemPropertiesProto::EXTRA_PROPERTIES); - proto.write(SystemPropertiesProto::Property::NAME, name); - proto.write(SystemPropertiesProto::Property::VALUE, value); - proto.end(token); + if (!sysProp.insertField(&proto, convertToFieldName(name), value)) { + extras.push_back(make_pair(name, value)); } } + // end session for the last write. + sysProp.endSession(&proto); + + for (auto it = extras.begin(); it != extras.end(); it++) { + long long token = proto.start(SystemPropertiesProto::EXTRA_PROPERTIES); + proto.write(SystemPropertiesProto::Property::NAME, it->first); + proto.write(SystemPropertiesProto::Property::VALUE, it->second); + proto.end(token); + } if (!reader.ok(&line)) { fprintf(stderr, "Bad read from fd %d: %s\n", in, line.c_str()); diff --git a/cmds/incident_helper/testdata/system_properties.txt b/cmds/incident_helper/testdata/system_properties.txt index 57c07ee9d75e..51a2dfd96869 100644 --- a/cmds/incident_helper/testdata/system_properties.txt +++ b/cmds/incident_helper/testdata/system_properties.txt @@ -1,14 +1,13 @@ [aaudio.hw_burst_min_usec]: [2000] [aaudio.mmap_exclusive_policy]: [2] [dalvik.vm.appimageformat]: [lz4] -[gsm.operator.isroaming]: [false] -[init.svc.vendor.imsqmidaemon]: [running] -[init.svc.vendor.init-radio-sh]: [stopped] -[net.dns1]: [2001:4860:4860::8844] -[net.tcp.buffersize.wifi]: [524288,2097152,4194304,262144,524288,1048576] -[nfc.initialized]: [True] -[persist_radio_VT_ENABLE]: [1] +[drm_64bit_enabled]: [false] +[init.svc.adbd]: [running] +[init.svc.lmkd]: [stopped] +[media_mediadrmservice_enable]: [True] [ro.boot.boottime]: [1BLL:85,1BLE:898,2BLL:0,2BLE:862,SW:6739,KL:340] [ro.bootimage.build.date.utc]: [1509394807] [ro.bootimage.build.fingerprint]: [google/marlin/marlin:P/MASTER/jinyithu10301320:eng/dev-keys] -[ro.wifi.channels]: []
\ No newline at end of file +[ro.hardware]: [marlin] +[ro.hardware.power]: [marlin-profile] +[ro.wifi.channels]: [] diff --git a/cmds/incident_helper/tests/SystemPropertiesParser_test.cpp b/cmds/incident_helper/tests/SystemPropertiesParser_test.cpp index 23e292a512b9..98838e98d796 100644 --- a/cmds/incident_helper/tests/SystemPropertiesParser_test.cpp +++ b/cmds/incident_helper/tests/SystemPropertiesParser_test.cpp @@ -61,29 +61,38 @@ TEST_F(SystemPropertiesParserTest, HasSwapInfo) { SystemPropertiesParser parser; SystemPropertiesProto expected; - expected.set_aaudio_hw_burst_min_usec(2000); - expected.set_aaudio_mmap_exclusive_policy(2); - expected.set_dalvik_vm_appimageformat("lz4"); - expected.set_gsm_operator_isroaming(false); - expected.set_init_svc_vendor_imsqmidaemon(SystemPropertiesProto_Status_STATUS_RUNNING); - expected.set_init_svc_vendor_init_radio_sh(SystemPropertiesProto_Status_STATUS_STOPPED); - expected.set_net_dns1("2001:4860:4860::8844"); - expected.add_net_tcp_buffersize_wifi(524288); - expected.add_net_tcp_buffersize_wifi(2097152); - expected.add_net_tcp_buffersize_wifi(4194304); - expected.add_net_tcp_buffersize_wifi(262144); - expected.add_net_tcp_buffersize_wifi(524288); - expected.add_net_tcp_buffersize_wifi(1048576); - expected.set_nfc_initialized(true); - expected.set_persist_radio_vt_enable(1); - expected.add_ro_boot_boottime("1BLL:85"); - expected.add_ro_boot_boottime("1BLE:898"); - expected.add_ro_boot_boottime("2BLL:0"); - expected.add_ro_boot_boottime("2BLE:862"); - expected.add_ro_boot_boottime("SW:6739"); - expected.add_ro_boot_boottime("KL:340"); - expected.set_ro_bootimage_build_date_utc(1509394807LL); - expected.set_ro_bootimage_build_fingerprint("google/marlin/marlin:P/MASTER/jinyithu10301320:eng/dev-keys"); + SystemPropertiesProto::Aaudio* aaudio = expected.mutable_aaudio(); + aaudio->set_hw_burst_min_usec(2000); + aaudio->set_mmap_exclusive_policy(2); + + SystemPropertiesProto::DalvikVm* dalvikVm = expected.mutable_dalvik_vm(); + dalvikVm->set_appimageformat("lz4"); + + expected.set_drm_64bit_enabled(false); + + SystemPropertiesProto::InitSvc* initSvc = expected.mutable_init_svc(); + initSvc->set_adbd(SystemPropertiesProto_InitSvc_Status_STATUS_RUNNING); + initSvc->set_lmkd(SystemPropertiesProto_InitSvc_Status_STATUS_STOPPED); + + expected.set_media_mediadrmservice_enable(true); + + SystemPropertiesProto::Ro* ro = expected.mutable_ro(); + + SystemPropertiesProto::Ro::Boot* boot = ro->mutable_boot(); + boot->add_boottime("1BLL:85"); + boot->add_boottime("1BLE:898"); + boot->add_boottime("2BLL:0"); + boot->add_boottime("2BLE:862"); + boot->add_boottime("SW:6739"); + boot->add_boottime("KL:340"); + + SystemPropertiesProto::Ro::BootImage* bootimage = ro->mutable_bootimage(); + bootimage->set_build_date_utc(1509394807LL); + bootimage->set_build_fingerprint("google/marlin/marlin:P/MASTER/jinyithu10301320:eng/dev-keys"); + + SystemPropertiesProto::Ro::Hardware* hardware = ro->mutable_hardware(); + hardware->set_value("marlin"); + hardware->set_power("marlin-profile"); int fd = open(testFile.c_str(), O_RDONLY); ASSERT_TRUE(fd != -1); diff --git a/cmds/incidentd/Android.mk b/cmds/incidentd/Android.mk index cb5fd02ef30b..fb8ef6338d90 100644 --- a/cmds/incidentd/Android.mk +++ b/cmds/incidentd/Android.mk @@ -120,14 +120,6 @@ LOCAL_SHARED_LIBRARIES := \ libservices \ libutils \ -relative_path_prefix := nativetest64/incidentd_test -testdata_files := $(call find-subdir-files, testdata/*) - -GEN := $(addprefix $(TARGET_OUT_DATA)/$(relative_path_prefix)/, $(testdata_files)) -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = cp $< $@ -$(GEN): $(TARGET_OUT_DATA)/$(relative_path_prefix)/testdata/% : $(LOCAL_PATH)/testdata/% - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) +LOCAL_TEST_DATA := $(call find-test-data-in-subdirs, $(LOCAL_PATH), *, testdata) include $(BUILD_NATIVE_TEST) diff --git a/cmds/incidentd/AndroidTest.xml b/cmds/incidentd/AndroidTest.xml new file mode 100644 index 000000000000..7f0e4ee305e3 --- /dev/null +++ b/cmds/incidentd/AndroidTest.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> +<configuration description="Config for incidentd_test"> + <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"> + <option name="cleanup" value="true" /> + <option name="push" value="incidentd_test->/data/nativetest/incidentd_test" /> + <option name="push" value="testdata->/data/nativetest/testdata" /> + </target_preparer> + <option name="test-suite-tag" value="apct" /> + <test class="com.android.tradefed.testtype.GTest" > + <option name="native-test-device-path" value="/data/nativetest" /> + <option name="module-name" value="incidentd_test" /> + </test> +</configuration> diff --git a/cmds/incidentd/README.md b/cmds/incidentd/README.md index daa39248e3f8..ad0fa08c7326 100644 --- a/cmds/incidentd/README.md +++ b/cmds/incidentd/README.md @@ -5,13 +5,19 @@ For the first time, build the test and create an empty directly on device: ``` -root$ make -j incidentd_test && adb shell mkdir /data/nativetest64/incidentd_test +root$ make -j incidentd_test && adb shell mkdir /data/nativetest/incidentd_test ``` -Run the test on a device +Run the test on a device manually ``` root$ mmm -j frameworks/base/cmds/incidentd && \ -adb push $OUT/data/nativetest64/incidentd_test/* /data/nativetest64/incidentd_test/ && \ -adb shell /data/nativetest64/incidentd_test/incidentd_test 2>/dev/null +adb push $OUT/data/nativetest/incidentd_test/* /data/nativetest/incidentd_test/ && \ +adb shell /data/nativetest/incidentd_test/incidentd_test 2>/dev/null ``` + +Run the test via AndroidTest.xml + +``` +root$ atest incidentd_test +```
\ No newline at end of file diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk index 337aeaaf37ab..ef7d31b22d32 100644 --- a/cmds/statsd/Android.mk +++ b/cmds/statsd/Android.mk @@ -126,7 +126,7 @@ LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries) \ LOCAL_MODULE_CLASS := EXECUTABLES -#LOCAL_INIT_RC := statsd.rc +LOCAL_INIT_RC := statsd.rc include $(BUILD_EXECUTABLE) diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index 2df0c90e9baf..7589b9387924 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -58,7 +58,7 @@ const int FIELD_ID_NAME = 2; const int FIELD_ID_METRICS = 1; const int FIELD_ID_UID_MAP = 2; -#define STATS_DATA_DIR "/data/system/stats-data" +#define STATS_DATA_DIR "/data/misc/stats-data" StatsLogProcessor::StatsLogProcessor(const sp<UidMap>& uidMap, const sp<AnomalyMonitor>& anomalyMonitor, diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index dc12efb2666e..d8f0facbaa9b 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -46,7 +46,7 @@ namespace os { namespace statsd { constexpr const char* kPermissionDump = "android.permission.DUMP"; -#define STATS_SERVICE_DIR "/data/system/stats-service" +#define STATS_SERVICE_DIR "/data/misc/stats-service" // ====================================================================== /** diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp index 540199d59910..e52b2739c991 100644 --- a/cmds/statsd/src/config/ConfigManager.cpp +++ b/cmds/statsd/src/config/ConfigManager.cpp @@ -29,7 +29,7 @@ namespace android { namespace os { namespace statsd { -#define STATS_SERVICE_DIR "/data/system/stats-service" +#define STATS_SERVICE_DIR "/data/misc/stats-service" using android::base::StringPrintf; using std::unique_ptr; diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp index 62f06a760656..3a4dfdaaf54d 100644 --- a/cmds/statsd/src/storage/StorageManager.cpp +++ b/cmds/statsd/src/storage/StorageManager.cpp @@ -30,7 +30,7 @@ namespace android { namespace os { namespace statsd { -#define STATS_SERVICE_DIR "/data/system/stats-service" +#define STATS_SERVICE_DIR "/data/misc/stats-service" // for ConfigMetricsReportList const int FIELD_ID_REPORTS = 2; diff --git a/cmds/uiautomator/library/Android.mk b/cmds/uiautomator/library/Android.mk index 22cffe60b2a8..62a2865d0bcc 100644 --- a/cmds/uiautomator/library/Android.mk +++ b/cmds/uiautomator/library/Android.mk @@ -36,7 +36,7 @@ include $(BUILD_STATIC_JAVA_LIBRARY) # Generate the stub source files include $(CLEAR_VARS) LOCAL_SRC_FILES := $(uiautomator.core_src_files) -LOCAL_JAVA_LIBRARIES := $(uiautomator.core_java_libraries) legacy-android-test +LOCAL_JAVA_LIBRARIES := $(uiautomator.core_java_libraries) android.test.base LOCAL_MODULE_CLASS := JAVA_LIBRARIES LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/core-src \ $(LOCAL_PATH)/testrunner-src diff --git a/core/java/android/annotation/IntDef.java b/core/java/android/annotation/IntDef.java index 637fc1e6afe2..f84a67655dc3 100644 --- a/core/java/android/annotation/IntDef.java +++ b/core/java/android/annotation/IntDef.java @@ -52,7 +52,9 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; @Target({ANNOTATION_TYPE}) public @interface IntDef { /** Defines the constant prefix for this element */ - String[] prefix() default ""; + String[] prefix() default {}; + /** Defines the constant suffix for this element */ + String[] suffix() default {}; /** Defines the allowed constants for this element */ int[] value() default {}; diff --git a/core/java/android/annotation/StringDef.java b/core/java/android/annotation/StringDef.java index d5157c3a1562..a37535b9c98e 100644 --- a/core/java/android/annotation/StringDef.java +++ b/core/java/android/annotation/StringDef.java @@ -46,6 +46,11 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; @Retention(SOURCE) @Target({ANNOTATION_TYPE}) public @interface StringDef { + /** Defines the constant prefix for this element */ + String[] prefix() default {}; + /** Defines the constant suffix for this element */ + String[] suffix() default {}; + /** Defines the allowed constants for this element */ String[] value() default {}; } diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 142630e0d507..e33b79e51fb6 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -2613,7 +2613,7 @@ public class ActivityManager { Manifest.permission.ACCESS_INSTANT_APPS}) public boolean clearApplicationUserData(String packageName, IPackageDataObserver observer) { try { - return getService().clearApplicationUserData(packageName, + return getService().clearApplicationUserData(packageName, false, observer, UserHandle.myUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index d7efa91fb28b..a9c4d3705afc 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -299,4 +299,9 @@ public abstract class ActivityManagerInternal { * @return true if runtime was restarted, false if it's normal boot */ public abstract boolean isRuntimeRestarted(); + + /** + * Returns {@code true} if {@code uid} is running an activity from {@code packageName}. + */ + public abstract boolean hasRunningActivity(int uid, @Nullable String packageName); } diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index b6fb12018201..c1a51044e349 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -256,8 +256,10 @@ public class AppOpsManager { public static final int OP_RUN_ANY_IN_BACKGROUND = 70; /** @hide Change Wi-Fi connectivity state */ public static final int OP_CHANGE_WIFI_STATE = 71; + /** @hide Request package deletion through package installer */ + public static final int OP_REQUEST_DELETE_PACKAGES = 72; /** @hide */ - public static final int _NUM_OP = 72; + public static final int _NUM_OP = 73; /** Access to coarse location information. */ public static final String OPSTR_COARSE_LOCATION = "android:coarse_location"; @@ -410,6 +412,7 @@ public class AppOpsManager { OP_CAMERA, // Body sensors OP_BODY_SENSORS, + OP_REQUEST_DELETE_PACKAGES, // APPOP PERMISSIONS OP_ACCESS_NOTIFICATIONS, @@ -499,6 +502,7 @@ public class AppOpsManager { OP_ANSWER_PHONE_CALLS, OP_RUN_ANY_IN_BACKGROUND, OP_CHANGE_WIFI_STATE, + OP_REQUEST_DELETE_PACKAGES, }; /** @@ -578,6 +582,7 @@ public class AppOpsManager { OPSTR_ANSWER_PHONE_CALLS, null, // OP_RUN_ANY_IN_BACKGROUND null, // OP_CHANGE_WIFI_STATE + null, // OP_REQUEST_DELETE_PACKAGES }; /** @@ -657,6 +662,7 @@ public class AppOpsManager { "ANSWER_PHONE_CALLS", "RUN_ANY_IN_BACKGROUND", "CHANGE_WIFI_STATE", + "REQUEST_DELETE_PACKAGES", }; /** @@ -736,6 +742,7 @@ public class AppOpsManager { Manifest.permission.ANSWER_PHONE_CALLS, null, // no permission for OP_RUN_ANY_IN_BACKGROUND Manifest.permission.CHANGE_WIFI_STATE, + Manifest.permission.REQUEST_DELETE_PACKAGES, }; /** @@ -816,6 +823,7 @@ public class AppOpsManager { null, // ANSWER_PHONE_CALLS null, // OP_RUN_ANY_IN_BACKGROUND null, // OP_CHANGE_WIFI_STATE + null, // REQUEST_DELETE_PACKAGES }; /** @@ -895,6 +903,7 @@ public class AppOpsManager { false, // ANSWER_PHONE_CALLS false, // OP_RUN_ANY_IN_BACKGROUND false, // OP_CHANGE_WIFI_STATE + false, // OP_REQUEST_DELETE_PACKAGES }; /** @@ -973,6 +982,7 @@ public class AppOpsManager { AppOpsManager.MODE_ALLOWED, // ANSWER_PHONE_CALLS AppOpsManager.MODE_ALLOWED, // OP_RUN_ANY_IN_BACKGROUND AppOpsManager.MODE_ALLOWED, // OP_CHANGE_WIFI_STATE + AppOpsManager.MODE_ALLOWED, // REQUEST_DELETE_PACKAGES }; /** @@ -1055,6 +1065,7 @@ public class AppOpsManager { false, // ANSWER_PHONE_CALLS false, // OP_RUN_ANY_IN_BACKGROUND false, // OP_CHANGE_WIFI_STATE + false, // OP_REQUEST_DELETE_PACKAGES }; /** diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 84c07ec7f45a..85bf6aa75f56 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -207,7 +207,7 @@ interface IActivityManager { boolean moveActivityTaskToBack(in IBinder token, boolean nonRoot); void getMemoryInfo(out ActivityManager.MemoryInfo outInfo); List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState(); - boolean clearApplicationUserData(in String packageName, + boolean clearApplicationUserData(in String packageName, boolean keepState, in IPackageDataObserver observer, int userId); void forceStopPackage(in String packageName, int userId); boolean killPids(in int[] pids, in String reason, boolean secure); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 562b981941a7..cfff3614a8e4 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1321,9 +1321,15 @@ public class DevicePolicyManager { public static final String DELEGATION_ENABLE_SYSTEM_APP = "delegation-enable-system-app"; /** + * Delegation for installing existing packages. This scope grants access to the + * {@link #installExistingPackage} API. + */ + public static final String DELEGATION_INSTALL_EXISTING_PACKAGE = + "delegation-install-existing-package"; + + /** * Delegation of management of uninstalled packages. This scope grants access to the * {@code #setKeepUninstalledPackages} and {@code #getKeepUninstalledPackages} APIs. - * @hide */ public static final String DELEGATION_KEEP_UNINSTALLED_PACKAGES = "delegation-keep-uninstalled-packages"; @@ -3474,6 +3480,16 @@ public class DevicePolicyManager { @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_START_ENCRYPTION = "android.app.action.START_ENCRYPTION"; + + /** + * Broadcast action: notify managed provisioning that new managed user is created. + * + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_MANAGED_USER_CREATED = + "android.app.action.MANAGED_USER_CREATED"; + /** * Widgets are enabled in keyguard */ @@ -6085,7 +6101,6 @@ public class DevicePolicyManager { * @return List of package names to keep cached. * @see #setDelegatedScopes * @see #DELEGATION_KEEP_UNINSTALLED_PACKAGES - * @hide */ public @Nullable List<String> getKeepUninstalledPackages(@Nullable ComponentName admin) { throwIfParentInstance("getKeepUninstalledPackages"); @@ -6113,7 +6128,6 @@ public class DevicePolicyManager { * @throws SecurityException if {@code admin} is not a device owner. * @see #setDelegatedScopes * @see #DELEGATION_KEEP_UNINSTALLED_PACKAGES - * @hide */ public void setKeepUninstalledPackages(@Nullable ComponentName admin, @NonNull List<String> packageNames) { @@ -6201,20 +6215,25 @@ public class DevicePolicyManager { public static final int MAKE_USER_DEMO = 0x0004; /** - * Flag used by {@link #createAndManageUser} to specificy that the newly created user should be + * Flag used by {@link #createAndManageUser} to specify that the newly created user should be * started in the background as part of the user creation. */ - // TODO: Investigate solutions for the case where reboot happens before setup is completed. public static final int START_USER_IN_BACKGROUND = 0x0008; /** + * Flag used by {@link #createAndManageUser} to specify that the newly created user should skip + * the disabling of system apps during provisioning. + */ + public static final int LEAVE_ALL_SYSTEM_APPS_ENABLED = 0x0010; + + /** * @hide */ @IntDef( flag = true, - prefix = {"SKIP_", "MAKE_USER_", "START_"}, + prefix = {"SKIP_", "MAKE_USER_", "START_", "LEAVE_"}, value = {SKIP_SETUP_WIZARD, MAKE_USER_EPHEMERAL, MAKE_USER_DEMO, - START_USER_IN_BACKGROUND} + START_USER_IN_BACKGROUND, LEAVE_ALL_SYSTEM_APPS_ENABLED} ) @Retention(RetentionPolicy.SOURCE) public @interface CreateAndManageUserFlags {} @@ -6357,6 +6376,21 @@ public class DevicePolicyManager { } /** + * Checks if the profile owner is running in an ephemeral user. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @return whether the profile owner is running in an ephemeral user. + */ + public boolean isEphemeralUser(@NonNull ComponentName admin) { + throwIfParentInstance("isEphemeralUser"); + try { + return mService.isEphemeralUser(admin); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** * Retrieves the application restrictions for a given target application running in the calling * user. * <p> @@ -6591,6 +6625,37 @@ public class DevicePolicyManager { } /** + * Install an existing package that has been installed in another user, or has been kept after + * removal via {@link #setKeepUninstalledPackages}. + * This function can be called by a device owner, profile owner or a delegate given + * the {@link #DELEGATION_INSTALL_EXISTING_PACKAGE} scope via {@link #setDelegatedScopes}. + * When called in a secondary user or managed profile, the user/profile must be affiliated with + * the device owner. See {@link #setAffiliationIds}. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageName The package to be installed in the calling profile. + * @return {@code true} if the app is installed; {@code false} otherwise. + * @throws SecurityException if {@code admin} is not the device owner, or the profile owner of + * an affiliated user or profile. + * @see #setKeepUninstalledPackages + * @see #setDelegatedScopes + * @see #setAffiliationIds + * @see #DELEGATION_PACKAGE_ACCESS + */ + public boolean installExistingPackage(@NonNull ComponentName admin, String packageName) { + throwIfParentInstance("installExistingPackage"); + if (mService != null) { + try { + return mService.installExistingPackage(admin, mContext.getPackageName(), + packageName); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + return false; + } + + /** * Called by a device owner or profile owner to disable account management for a specific type * of account. * <p> @@ -8585,32 +8650,31 @@ public class DevicePolicyManager { } /** - * Called by a device owner to specify whether a logout button is enabled for all secondary - * users. The system may show a logout button that stops the user and switches back to the - * primary user. + * Called by a device owner to specify whether logout is enabled for all secondary users. The + * system may show a logout button that stops the user and switches back to the primary user. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @param enabled whether logout button should be enabled or not. + * @param enabled whether logout should be enabled or not. * @throws SecurityException if {@code admin} is not a device owner. */ - public void setLogoutButtonEnabled(@NonNull ComponentName admin, boolean enabled) { - throwIfParentInstance("setLogoutButtonEnabled"); + public void setLogoutEnabled(@NonNull ComponentName admin, boolean enabled) { + throwIfParentInstance("setLogoutEnabled"); try { - mService.setLogoutButtonEnabled(admin, enabled); + mService.setLogoutEnabled(admin, enabled); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } } /** - * Returns whether logout button is enabled by a device owner. + * Returns whether logout is enabled by a device owner. * - * @return {@code true} if logout button is enabled by device owner, {@code false} otherwise. + * @return {@code true} if logout is enabled by device owner, {@code false} otherwise. */ - public boolean isLogoutButtonEnabled() { - throwIfParentInstance("isLogoutButtonEnabled"); + public boolean isLogoutEnabled() { + throwIfParentInstance("isLogoutEnabled"); try { - return mService.isLogoutButtonEnabled(); + return mService.isLogoutEnabled(); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -8630,4 +8694,25 @@ public class DevicePolicyManager { */ void onApplicationUserDataCleared(String packageName, boolean succeeded); } + + /** + * Returns set of system apps that should be removed during provisioning. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param userId ID of the user to be provisioned. + * @param provisioningAction action indicating type of provisioning, should be one of + * {@link #ACTION_PROVISION_MANAGED_DEVICE}, {@link #ACTION_PROVISION_MANAGED_PROFILE} or + * {@link #ACTION_PROVISION_MANAGED_USER}. + * + * @hide + */ + public Set<String> getDisallowedSystemApps(ComponentName admin, int userId, + String provisioningAction) { + try { + return new ArraySet<>( + mService.getDisallowedSystemApps(admin, userId, provisioningAction)); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index c525df725d47..b76618b25e7d 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -223,6 +223,7 @@ interface IDevicePolicyManager { void enableSystemApp(in ComponentName admin, in String callerPackage, in String packageName); int enableSystemAppWithIntent(in ComponentName admin, in String callerPackage, in Intent intent); + boolean installExistingPackage(in ComponentName admin, in String callerPackage, in String packageName); void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled); String[] getAccountTypesWithManagementDisabled(); @@ -357,6 +358,7 @@ interface IDevicePolicyManager { IApplicationThread caller, IBinder token, in Intent service, IServiceConnection connection, int flags, int targetUserId); List<UserHandle> getBindDeviceAdminTargetUsers(in ComponentName admin); + boolean isEphemeralUser(in ComponentName admin); long getLastSecurityLogRetrievalTime(); long getLastBugReportRequestTime(); @@ -372,6 +374,8 @@ interface IDevicePolicyManager { boolean clearApplicationUserData(in ComponentName admin, in String packageName, in IPackageDataObserver callback); - void setLogoutButtonEnabled(in ComponentName admin, boolean enabled); - boolean isLogoutButtonEnabled(); + void setLogoutEnabled(in ComponentName admin, boolean enabled); + boolean isLogoutEnabled(); + + List<String> getDisallowedSystemApps(in ComponentName admin, int userId, String provisioningAction); } diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java index ddc5760a6b3d..b13067ee97e3 100644 --- a/core/java/android/app/slice/Slice.java +++ b/core/java/android/app/slice/Slice.java @@ -37,6 +37,8 @@ import android.os.RemoteException; import com.android.internal.util.ArrayUtils; import com.android.internal.util.Preconditions; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -53,9 +55,21 @@ public final class Slice implements Parcelable { /** * @hide */ - @StringDef({HINT_TITLE, HINT_LIST, HINT_LIST_ITEM, HINT_LARGE, HINT_ACTIONS, HINT_SELECTED, - HINT_NO_TINT, HINT_PARTIAL}) - public @interface SliceHint{ } + @StringDef(prefix = { "HINT_" }, value = { + HINT_TITLE, + HINT_LIST, + HINT_LIST_ITEM, + HINT_LARGE, + HINT_ACTIONS, + HINT_SELECTED, + HINT_NO_TINT, + HINT_HIDDEN, + HINT_TOGGLE, + HINT_HORIZONTAL, + HINT_PARTIAL, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SliceHint {} /** * The meta-data key that allows an activity to easily be linked directly to a slice. @@ -129,6 +143,11 @@ public final class Slice implements Parcelable { * OS and should not be cached by apps. */ public static final String HINT_PARTIAL = "partial"; + /** + * A hint representing that this item is the max value possible for the slice containing this. + * Used to indicate the maximum integer value for a {@link #SUBTYPE_SLIDER}. + */ + public static final String HINT_MAX = "max"; /** * Key to retrieve an extra added to an intent when a control is changed. @@ -144,6 +163,14 @@ public final class Slice implements Parcelable { * Subtype to tag the source (i.e. sender) of a {@link #SUBTYPE_MESSAGE}. */ public static final String SUBTYPE_SOURCE = "source"; + /** + * Subtype to tag an item as representing a color. + */ + public static final String SUBTYPE_COLOR = "color"; + /** + * Subtype to tag an item represents a slider. + */ + public static final String SUBTYPE_SLIDER = "slider"; private final SliceItem[] mItems; private final @SliceHint String[] mHints; @@ -375,9 +402,10 @@ public final class Slice implements Parcelable { * Add a color to the slice being constructed * @param subType Optional template-specific type information * @see {@link SliceItem#getSubType()} + * @deprecated will be removed once supportlib updates */ public Builder addColor(int color, @Nullable String subType, @SliceHint String... hints) { - mItems.add(new SliceItem(color, SliceItem.FORMAT_COLOR, subType, hints)); + mItems.add(new SliceItem(color, SliceItem.FORMAT_INT, subType, hints)); return this; } @@ -385,6 +413,7 @@ public final class Slice implements Parcelable { * Add a color to the slice being constructed * @param subType Optional template-specific type information * @see {@link SliceItem#getSubType()} + * @deprecated will be removed once supportlib updates */ public Builder addColor(int color, @Nullable String subType, @SliceHint List<String> hints) { @@ -392,6 +421,26 @@ public final class Slice implements Parcelable { } /** + * Add a color to the slice being constructed + * @param subType Optional template-specific type information + * @see {@link SliceItem#getSubType()} + */ + public Builder addInt(int value, @Nullable String subType, @SliceHint String... hints) { + mItems.add(new SliceItem(value, SliceItem.FORMAT_INT, subType, hints)); + return this; + } + + /** + * Add a color to the slice being constructed + * @param subType Optional template-specific type information + * @see {@link SliceItem#getSubType()} + */ + public Builder addInt(int value, @Nullable String subType, + @SliceHint List<String> hints) { + return addInt(value, subType, hints.toArray(new String[hints.size()])); + } + + /** * Add a timestamp to the slice being constructed * @param subType Optional template-specific type information * @see {@link SliceItem#getSubType()} @@ -414,6 +463,32 @@ public final class Slice implements Parcelable { } /** + * Add a bundle to the slice being constructed. + * <p>Expected to be used for support library extension, should not be used for general + * development + * @param subType Optional template-specific type information + * @see {@link SliceItem#getSubType()} + */ + public Slice.Builder addBundle(Bundle bundle, @Nullable String subType, + @SliceHint String... hints) { + mItems.add(new SliceItem(bundle, SliceItem.FORMAT_BUNDLE, subType, + hints)); + return this; + } + + /** + * Add a bundle to the slice being constructed. + * <p>Expected to be used for support library extension, should not be used for general + * development + * @param subType Optional template-specific type information + * @see {@link SliceItem#getSubType()} + */ + public Slice.Builder addBundle(Bundle bundle, @Nullable String subType, + @SliceHint List<String> hints) { + return addBundle(bundle, subType, hints.toArray(new String[hints.size()])); + } + + /** * Construct the slice. */ public Slice build() { diff --git a/core/java/android/app/slice/SliceItem.java b/core/java/android/app/slice/SliceItem.java index cdeee3575756..bcfd413fb823 100644 --- a/core/java/android/app/slice/SliceItem.java +++ b/core/java/android/app/slice/SliceItem.java @@ -21,6 +21,7 @@ import android.annotation.StringDef; import android.app.PendingIntent; import android.app.RemoteInput; import android.graphics.drawable.Icon; +import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -29,6 +30,8 @@ import android.widget.RemoteViews; import com.android.internal.util.ArrayUtils; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.List; @@ -42,9 +45,10 @@ import java.util.List; * <li>{@link #FORMAT_TEXT}</li> * <li>{@link #FORMAT_IMAGE}</li> * <li>{@link #FORMAT_ACTION}</li> - * <li>{@link #FORMAT_COLOR}</li> + * <li>{@link #FORMAT_INT}</li> * <li>{@link #FORMAT_TIMESTAMP}</li> * <li>{@link #FORMAT_REMOTE_INPUT}</li> + * <li>{@link #FORMAT_BUNDLE}</li> * * The hints that a {@link SliceItem} are a set of strings which annotate * the content. The hints that are guaranteed to be understood by the system @@ -52,11 +56,22 @@ import java.util.List; */ public final class SliceItem implements Parcelable { + private static final String TAG = "SliceItem"; + /** * @hide */ - @StringDef({FORMAT_SLICE, FORMAT_TEXT, FORMAT_IMAGE, FORMAT_ACTION, FORMAT_COLOR, - FORMAT_TIMESTAMP, FORMAT_REMOTE_INPUT}) + @StringDef(prefix = { "FORMAT_" }, value = { + FORMAT_SLICE, + FORMAT_TEXT, + FORMAT_IMAGE, + FORMAT_ACTION, + FORMAT_INT, + FORMAT_TIMESTAMP, + FORMAT_REMOTE_INPUT, + FORMAT_BUNDLE, + }) + @Retention(RetentionPolicy.SOURCE) public @interface SliceType {} /** @@ -79,7 +94,12 @@ public final class SliceItem implements Parcelable { */ public static final String FORMAT_ACTION = "action"; /** - * A {@link SliceItem} that contains a Color int. + * A {@link SliceItem} that contains an int. + */ + public static final String FORMAT_INT = "int"; + /** + * A {@link SliceItem} that contains an int. + * @deprecated to be removed */ public static final String FORMAT_COLOR = "color"; /** @@ -90,6 +110,10 @@ public final class SliceItem implements Parcelable { * A {@link SliceItem} that contains a {@link RemoteInput}. */ public static final String FORMAT_REMOTE_INPUT = "input"; + /** + * A {@link SliceItem} that contains a {@link Bundle}. + */ + public static final String FORMAT_BUNDLE = "bundle"; /** * @hide @@ -128,20 +152,6 @@ public final class SliceItem implements Parcelable { } /** - * @hide - */ - public void addHint(@Slice.SliceHint String hint) { - mHints = ArrayUtils.appendElement(String.class, mHints, hint); - } - - /** - * @hide - */ - public void removeHint(String hint) { - ArrayUtils.removeElement(String.class, mHints, hint); - } - - /** * Get the format of this SliceItem. * <p> * The format will be one of the following types supported by the platform: @@ -149,9 +159,10 @@ public final class SliceItem implements Parcelable { * <li>{@link #FORMAT_TEXT}</li> * <li>{@link #FORMAT_IMAGE}</li> * <li>{@link #FORMAT_ACTION}</li> - * <li>{@link #FORMAT_COLOR}</li> + * <li>{@link #FORMAT_INT}</li> * <li>{@link #FORMAT_TIMESTAMP}</li> * <li>{@link #FORMAT_REMOTE_INPUT}</li> + * <li>{@link #FORMAT_BUNDLE}</li> * @see #getSubType() () */ public String getFormat() { @@ -178,6 +189,13 @@ public final class SliceItem implements Parcelable { } /** + * @return The parcelable held by this {@link #FORMAT_BUNDLE} SliceItem + */ + public Bundle getBundle() { + return (Bundle) mObj; + } + + /** * @return The icon held by this {@link #FORMAT_IMAGE} SliceItem */ public Icon getIcon() { @@ -206,7 +224,14 @@ public final class SliceItem implements Parcelable { } /** - * @return The color held by this {@link #FORMAT_COLOR} SliceItem + * @return The color held by this {@link #FORMAT_INT} SliceItem + */ + public int getInt() { + return (Integer) mObj; + } + + /** + * @deprecated to be removed. */ public int getColor() { return (Integer) mObj; @@ -299,6 +324,7 @@ public final class SliceItem implements Parcelable { case FORMAT_SLICE: case FORMAT_IMAGE: case FORMAT_REMOTE_INPUT: + case FORMAT_BUNDLE: ((Parcelable) obj).writeToParcel(dest, flags); break; case FORMAT_ACTION: @@ -308,7 +334,7 @@ public final class SliceItem implements Parcelable { case FORMAT_TEXT: TextUtils.writeToParcel((CharSequence) obj, dest, flags); break; - case FORMAT_COLOR: + case FORMAT_INT: dest.writeInt((Integer) obj); break; case FORMAT_TIMESTAMP: @@ -329,12 +355,14 @@ public final class SliceItem implements Parcelable { return new Pair<>( PendingIntent.CREATOR.createFromParcel(in), Slice.CREATOR.createFromParcel(in)); - case FORMAT_COLOR: + case FORMAT_INT: return in.readInt(); case FORMAT_TIMESTAMP: return in.readLong(); case FORMAT_REMOTE_INPUT: return RemoteInput.CREATOR.createFromParcel(in); + case FORMAT_BUNDLE: + return Bundle.CREATOR.createFromParcel(in); } throw new RuntimeException("Unsupported type " + type); } diff --git a/core/java/android/app/timezone/RulesManager.java b/core/java/android/app/timezone/RulesManager.java index ad9b698a8fd7..417e7d26f4f5 100644 --- a/core/java/android/app/timezone/RulesManager.java +++ b/core/java/android/app/timezone/RulesManager.java @@ -105,9 +105,9 @@ public final class RulesManager { */ public RulesState getRulesState() { try { - logDebug("sIRulesManager.getRulesState()"); + logDebug("mIRulesManager.getRulesState()"); RulesState rulesState = mIRulesManager.getRulesState(); - logDebug("sIRulesManager.getRulesState() returned " + rulesState); + logDebug("mIRulesManager.getRulesState() returned " + rulesState); return rulesState; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -131,7 +131,7 @@ public final class RulesManager { ICallback iCallback = new CallbackWrapper(mContext, callback); try { - logDebug("sIRulesManager.requestInstall()"); + logDebug("mIRulesManager.requestInstall()"); return mIRulesManager.requestInstall(distroFileDescriptor, checkToken, iCallback); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -151,7 +151,7 @@ public final class RulesManager { public int requestUninstall(byte[] checkToken, Callback callback) { ICallback iCallback = new CallbackWrapper(mContext, callback); try { - logDebug("sIRulesManager.requestUninstall()"); + logDebug("mIRulesManager.requestUninstall()"); return mIRulesManager.requestUninstall(checkToken, iCallback); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -196,7 +196,7 @@ public final class RulesManager { */ public void requestNothing(byte[] checkToken, boolean succeeded) { try { - logDebug("sIRulesManager.requestNothing() with token=" + Arrays.toString(checkToken)); + logDebug("mIRulesManager.requestNothing() with token=" + Arrays.toString(checkToken)); mIRulesManager.requestNothing(checkToken, succeeded); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); diff --git a/core/java/android/app/usage/IStorageStatsManager.aidl b/core/java/android/app/usage/IStorageStatsManager.aidl index 15e5ea5f44ff..7eacc8996bb9 100644 --- a/core/java/android/app/usage/IStorageStatsManager.aidl +++ b/core/java/android/app/usage/IStorageStatsManager.aidl @@ -22,6 +22,7 @@ import android.app.usage.ExternalStorageStats; /** {@hide} */ interface IStorageStatsManager { boolean isQuotaSupported(String volumeUuid, String callingPackage); + boolean isReservedSupported(String volumeUuid, String callingPackage); long getTotalBytes(String volumeUuid, String callingPackage); long getFreeBytes(String volumeUuid, String callingPackage); long getCacheBytes(String volumeUuid, String callingPackage); diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl index 4fbbdf2a9281..f089c127d03f 100644 --- a/core/java/android/app/usage/IUsageStatsManager.aidl +++ b/core/java/android/app/usage/IUsageStatsManager.aidl @@ -19,6 +19,8 @@ package android.app.usage; import android.app.usage.UsageEvents; import android.content.pm.ParceledListSlice; +import java.util.Map; + /** * System private API for talking with the UsageStatsManagerService. * @@ -38,4 +40,6 @@ interface IUsageStatsManager { in String[] annotations, String action); int getAppStandbyBucket(String packageName, String callingPackage, int userId); void setAppStandbyBucket(String packageName, int bucket, int userId); + Map getAppStandbyBuckets(String callingPackage, int userId); + void setAppStandbyBuckets(in Map appBuckets, int userId); } diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java index 3d187ec7cb50..a86c27a03358 100644 --- a/core/java/android/app/usage/StorageStatsManager.java +++ b/core/java/android/app/usage/StorageStatsManager.java @@ -78,6 +78,16 @@ public class StorageStatsManager { return isQuotaSupported(convert(uuid)); } + /** {@hide} */ + @TestApi + public boolean isReservedSupported(@NonNull UUID storageUuid) { + try { + return mService.isReservedSupported(convert(storageUuid), mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Return the total size of the underlying physical media that is hosting * this storage volume. diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java index d614b20a0788..1fc45c9fdb94 100644 --- a/core/java/android/app/usage/UsageStatsManager.java +++ b/core/java/android/app/usage/UsageStatsManager.java @@ -324,11 +324,11 @@ public final class UsageStatsManager { * state of the app based on app usage patterns. Standby buckets determine how much an app will * be restricted from running background tasks such as jobs, alarms and certain PendingIntent * callbacks. - * Restrictions increase progressively from {@link #STANDBY_BUCKET_ACTIVE} to + * <p>Restrictions increase progressively from {@link #STANDBY_BUCKET_ACTIVE} to * {@link #STANDBY_BUCKET_RARE}, with {@link #STANDBY_BUCKET_ACTIVE} being the least * restrictive. The battery level of the device might also affect the restrictions. * - * @return the current standby bucket of the calling app. + * @return the current standby bucket of the calling app. One of STANDBY_BUCKET_* constants. */ public @StandbyBuckets int getAppStandbyBucket() { try { @@ -359,7 +359,13 @@ public final class UsageStatsManager { /** * {@hide} - * Changes the app standby state to the provided bucket. + * Changes an app's standby bucket to the provided value. The caller can only set the standby + * bucket for a different app than itself. + * @param packageName the package name of the app to set the bucket for. A SecurityException + * will be thrown if the package name is that of the caller. + * @param bucket the standby bucket to set it to, which should be one of STANDBY_BUCKET_*. + * Setting a standby bucket outside of the range of STANDBY_BUCKET_ACTIVE to + * STANDBY_BUCKET_NEVER will result in a SecurityException. */ @SystemApi @RequiresPermission(android.Manifest.permission.CHANGE_APP_IDLE_STATE) @@ -373,6 +379,39 @@ public final class UsageStatsManager { /** * {@hide} + * Returns the current standby bucket of every app that has a bucket assigned to it. + * The caller must hold the permission android.permission.PACKAGE_USAGE_STATS. The key of the + * returned Map is the package name and the value is the bucket assigned to the package. + * @see #getAppStandbyBucket() + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) + public Map<String, Integer> getAppStandbyBuckets() { + try { + return (Map<String, Integer>) mService.getAppStandbyBuckets( + mContext.getOpPackageName(), mContext.getUserId()); + } catch (RemoteException e) { + } + return Collections.EMPTY_MAP; + } + + /** + * {@hide} + * Changes the app standby bucket for multiple apps at once. The Map is keyed by the package + * name and the value is one of STANDBY_BUCKET_*. + * @param appBuckets a map of package name to bucket value. + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.CHANGE_APP_IDLE_STATE) + public void setAppStandbyBuckets(Map<String, Integer> appBuckets) { + try { + mService.setAppStandbyBuckets(appBuckets, mContext.getUserId()); + } catch (RemoteException e) { + } + } + + /** + * {@hide} * Temporarily whitelist the specified app for a short duration. This is to allow an app * receiving a high priority message to be able to access the network and acquire wakelocks * even if the device is in power-save mode or the app is currently considered inactive. diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java index a1a9347df690..794435457f25 100644 --- a/core/java/android/bluetooth/BluetoothPbap.java +++ b/core/java/android/bluetooth/BluetoothPbap.java @@ -25,6 +25,10 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Log; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** * The Android Bluetooth API is not finalized, and *will* change. Use at your * own risk. @@ -48,11 +52,10 @@ import android.util.Log; * * @hide */ -public class BluetoothPbap { +public class BluetoothPbap implements BluetoothProfile { private static final String TAG = "BluetoothPbap"; - private static final boolean DBG = true; - private static final boolean VDBG = false; + private static final boolean DBG = false; /** * Intent used to broadcast the change in connection state of the PBAP @@ -111,9 +114,9 @@ public class BluetoothPbap { private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { public void onBluetoothStateChange(boolean up) { - if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); + log("onBluetoothStateChange: up=" + up); if (!up) { - if (VDBG) Log.d(TAG, "Unbinding service..."); + log("Unbinding service..."); synchronized (mConnection) { try { mService = null; @@ -126,7 +129,7 @@ public class BluetoothPbap { synchronized (mConnection) { try { if (mService == null) { - if (VDBG) Log.d(TAG, "Binding service..."); + log("Binding service..."); doBind(); } } catch (Exception re) { @@ -205,47 +208,60 @@ public class BluetoothPbap { } /** - * Get the current state of the BluetoothPbap service. - * - * @return One of the STATE_ return codes, or {@link BluetoothProfile#STATE_DISCONNECTED} - * if this proxy object is currently not connected to the Pbap service. + * {@inheritDoc} */ - public int getState() { - if (VDBG) log("getState()"); + @Override + public List<BluetoothDevice> getConnectedDevices() { + log("getConnectedDevices()"); final IBluetoothPbap service = mService; - if (service != null) { - try { - return service.getState(); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); - } - } else { + if (service == null) { Log.w(TAG, "Proxy not attached to service"); - if (DBG) log(Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + try { + return service.getConnectedDevices(); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + return new ArrayList<BluetoothDevice>(); + } + + /** + * {@inheritDoc} + */ + @Override + public int getConnectionState(BluetoothDevice device) { + log("getConnectionState: device=" + device); + final IBluetoothPbap service = mService; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + return BluetoothProfile.STATE_DISCONNECTED; + } + try { + return service.getConnectionState(device); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); } return BluetoothProfile.STATE_DISCONNECTED; } /** - * Get the currently connected remote Bluetooth device (PCE). - * - * @return The remote Bluetooth device, or null if not in connected or connecting state, or if - * this proxy object is not connected to the Pbap service. + * {@inheritDoc} */ - public BluetoothDevice getClient() { - if (VDBG) log("getClient()"); + @Override + public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { + log("getDevicesMatchingConnectionStates: states=" + Arrays.toString(states)); final IBluetoothPbap service = mService; - if (service != null) { - try { - return service.getClient(); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); - } - } else { + if (service == null) { Log.w(TAG, "Proxy not attached to service"); - if (DBG) log(Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + try { + return service.getDevicesMatchingConnectionStates(states); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); } - return null; + return new ArrayList<BluetoothDevice>(); } /** @@ -253,20 +269,9 @@ public class BluetoothPbap { * include connecting). Returns false if not connected, or if this proxy * object is not currently connected to the Pbap service. */ + // TODO: This is currently being used by SettingsLib and internal app. public boolean isConnected(BluetoothDevice device) { - if (VDBG) log("isConnected(" + device + ")"); - final IBluetoothPbap service = mService; - if (service != null) { - try { - return service.isConnected(device); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); - } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) log(Log.getStackTraceString(new Throwable())); - } - return false; + return getConnectionState(device) == BluetoothAdapter.STATE_CONNECTED; } /** @@ -274,47 +279,27 @@ public class BluetoothPbap { * it may soon be made asynchronous. Returns false if this proxy object is * not currently connected to the Pbap service. */ - public boolean disconnect() { - if (DBG) log("disconnect()"); + // TODO: This is currently being used by SettingsLib and will be used in the future. + // TODO: Must specify target device. Implement this in the service. + public boolean disconnect(BluetoothDevice device) { + log("disconnect()"); final IBluetoothPbap service = mService; - if (service != null) { - try { - service.disconnect(); - return true; - } catch (RemoteException e) { - Log.e(TAG, e.toString()); - } - } else { + if (service == null) { Log.w(TAG, "Proxy not attached to service"); - if (DBG) log(Log.getStackTraceString(new Throwable())); + return false; } - return false; - } - - /** - * Check class bits for possible PBAP support. - * This is a simple heuristic that tries to guess if a device with the - * given class bits might support PBAP. It is not accurate for all - * devices. It tries to err on the side of false positives. - * - * @return True if this device might support PBAP. - */ - public static boolean doesClassMatchSink(BluetoothClass btClass) { - // TODO optimize the rule - switch (btClass.getDeviceClass()) { - case BluetoothClass.Device.COMPUTER_DESKTOP: - case BluetoothClass.Device.COMPUTER_LAPTOP: - case BluetoothClass.Device.COMPUTER_SERVER: - case BluetoothClass.Device.COMPUTER_UNCATEGORIZED: - return true; - default: - return false; + try { + service.disconnect(device); + return true; + } catch (RemoteException e) { + Log.e(TAG, e.toString()); } + return false; } private final ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { - if (DBG) log("Proxy object connected"); + log("Proxy object connected"); mService = IBluetoothPbap.Stub.asInterface(service); if (mServiceListener != null) { mServiceListener.onServiceConnected(BluetoothPbap.this); @@ -322,7 +307,7 @@ public class BluetoothPbap { } public void onServiceDisconnected(ComponentName className) { - if (DBG) log("Proxy object disconnected"); + log("Proxy object disconnected"); mService = null; if (mServiceListener != null) { mServiceListener.onServiceDisconnected(); @@ -331,6 +316,8 @@ public class BluetoothPbap { }; private static void log(String msg) { - Log.d(TAG, msg); + if (DBG) { + Log.d(TAG, msg); + } } } diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index 46a230b50605..ebbc710922c2 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -254,4 +254,28 @@ public interface BluetoothProfile { */ public void onServiceDisconnected(int profile); } + + /** + * Convert an integer value of connection state into human readable string + * + * @param connectionState - One of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, + * {@link #STATE_CONNECTED}, or {@link #STATE_DISCONNECTED} + * @return a string representation of the connection state, STATE_UNKNOWN if the state + * is not defined + * @hide + */ + static String getConnectionStateName(int connectionState) { + switch (connectionState) { + case STATE_DISCONNECTED: + return "STATE_DISCONNECTED"; + case STATE_CONNECTING: + return "STATE_CONNECTING"; + case STATE_CONNECTED: + return "STATE_CONNECTED"; + case STATE_DISCONNECTING: + return "STATE_DISCONNECTING"; + default: + return "STATE_UNKNOWN"; + } + } } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index f1b473710be4..a47433093988 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2913,7 +2913,7 @@ public abstract class Context { @Nullable String profileFile, @Nullable Bundle arguments); /** @hide */ - @StringDef({ + @StringDef(suffix = { "_SERVICE" }, value = { POWER_SERVICE, WINDOW_SERVICE, LAYOUT_INFLATER_SERVICE, diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 84b1ff3219a2..c73b853a02cb 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -26,6 +26,7 @@ import android.content.Context; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.graphics.drawable.Drawable; +import android.os.Build; import android.os.Environment; import android.os.Parcel; import android.os.Parcelable; @@ -1582,6 +1583,11 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { return (privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0; } + /** @hide */ + public boolean isTargetingDeprecatedSdkVersion() { + return targetSdkVersion < Build.VERSION.MIN_SUPPORTED_TARGET_SDK_INT; + } + /** * Returns whether or not this application was installed as a virtual preload. */ diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java index 0c893b0ff06a..5a91e94781d7 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -16,10 +16,14 @@ package android.content.pm; +import android.annotation.IntDef; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Overall information about the contents of a package. This corresponds * to all of the information collected from AndroidManifest.xml. @@ -330,8 +334,29 @@ public class PackageInfo implements Parcelable { /** @hide */ public int overlayPriority; - /** @hide */ - public boolean isStaticOverlay; + /** + * Flag for use with {@link #mOverlayFlags}. Marks the overlay as static, meaning it cannot + * be enabled/disabled at runtime. + */ + static final int FLAG_OVERLAY_STATIC = 1 << 1; + + /** + * Flag for use with {@link #mOverlayFlags}. Marks the overlay as trusted (not 3rd party). + */ + static final int FLAG_OVERLAY_TRUSTED = 1 << 2; + + @IntDef(flag = true, prefix = "FLAG_OVERLAY_", value = { + FLAG_OVERLAY_STATIC, + FLAG_OVERLAY_TRUSTED + }) + @Retention(RetentionPolicy.SOURCE) + @interface OverlayFlags {} + + /** + * Modifiers that affect the state of this overlay. See {@link #FLAG_OVERLAY_STATIC}, + * {@link #FLAG_OVERLAY_TRUSTED}. + */ + @OverlayFlags int mOverlayFlags; /** * The user-visible SDK version (ex. 26) of the framework against which the application claims @@ -359,6 +384,23 @@ public class PackageInfo implements Parcelable { public PackageInfo() { } + /** + * Returns true if the package is a valid Runtime Overlay package. + * @hide + */ + public boolean isOverlayPackage() { + return overlayTarget != null && (mOverlayFlags & FLAG_OVERLAY_TRUSTED) != 0; + } + + /** + * Returns true if the package is a valid static Runtime Overlay package. Static overlays + * are not updatable outside of a system update and are safe to load in the system process. + * @hide + */ + public boolean isStaticOverlayPackage() { + return overlayTarget != null && (mOverlayFlags & FLAG_OVERLAY_STATIC) != 0; + } + @Override public String toString() { return "PackageInfo{" @@ -410,8 +452,8 @@ public class PackageInfo implements Parcelable { dest.writeString(restrictedAccountType); dest.writeString(requiredAccountType); dest.writeString(overlayTarget); - dest.writeInt(isStaticOverlay ? 1 : 0); dest.writeInt(overlayPriority); + dest.writeInt(mOverlayFlags); dest.writeInt(compileSdkVersion); dest.writeString(compileSdkVersionCodename); } @@ -465,8 +507,8 @@ public class PackageInfo implements Parcelable { restrictedAccountType = source.readString(); requiredAccountType = source.readString(); overlayTarget = source.readString(); - isStaticOverlay = source.readInt() != 0; overlayPriority = source.readInt(); + mOverlayFlags = source.readInt(); compileSdkVersion = source.readInt(); compileSdkVersionCodename = source.readString(); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 153c944a8d93..97c2b7d11354 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -689,7 +689,15 @@ public class PackageParser { pi.requiredAccountType = p.mRequiredAccountType; pi.overlayTarget = p.mOverlayTarget; pi.overlayPriority = p.mOverlayPriority; - pi.isStaticOverlay = p.mIsStaticOverlay; + + if (p.mIsStaticOverlay) { + pi.mOverlayFlags |= PackageInfo.FLAG_OVERLAY_STATIC; + } + + if (p.mTrustedOverlay) { + pi.mOverlayFlags |= PackageInfo.FLAG_OVERLAY_TRUSTED; + } + pi.compileSdkVersion = p.mCompileSdkVersion; pi.compileSdkVersionCodename = p.mCompileSdkVersionCodename; pi.firstInstallTime = firstInstallTime; @@ -6454,6 +6462,7 @@ public class PackageParser { mAdoptPermissions = dest.createStringArrayList(); mAppMetaData = dest.readBundle(); mVersionCode = dest.readInt(); + mVersionCodeMajor = dest.readInt(); mVersionName = dest.readString(); if (mVersionName != null) { mVersionName = mVersionName.intern(); @@ -6600,6 +6609,7 @@ public class PackageParser { dest.writeStringList(mAdoptPermissions); dest.writeBundle(mAppMetaData); dest.writeInt(mVersionCode); + dest.writeInt(mVersionCodeMajor); dest.writeString(mVersionName); dest.writeString(mSharedUserId); dest.writeInt(mSharedUserLabel); diff --git a/services/core/java/com/android/server/timezone/ClockHelper.java b/core/java/android/hardware/display/BrightnessConfiguration.aidl index 353728a15e7c..5b6b4645fa45 100644 --- a/services/core/java/com/android/server/timezone/ClockHelper.java +++ b/core/java/android/hardware/display/BrightnessConfiguration.aidl @@ -14,12 +14,6 @@ * limitations under the License. */ -package com.android.server.timezone; +package android.hardware.display; -/** - * An easy-to-mock interface for obtaining a monotonically increasing time value in milliseconds. - */ -interface ClockHelper { - - long currentTimestamp(); -} +parcelable BrightnessConfiguration; diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java new file mode 100644 index 000000000000..6c3be816e87b --- /dev/null +++ b/core/java/android/hardware/display/BrightnessConfiguration.java @@ -0,0 +1,175 @@ +/* + * 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.hardware.display; + +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Pair; + +import com.android.internal.util.Preconditions; + +import java.util.Arrays; + +/** @hide */ +public final class BrightnessConfiguration implements Parcelable { + private final float[] mLux; + private final float[] mNits; + + private BrightnessConfiguration(float[] lux, float[] nits) { + mLux = lux; + mNits = nits; + } + + /** + * Gets the base brightness as curve. + * + * The curve is returned as a pair of float arrays, the first representing all of the lux + * points of the brightness curve and the second representing all of the nits values of the + * brightness curve. + * + * @return the control points for the brightness curve. + */ + public Pair<float[], float[]> getCurve() { + return Pair.create(Arrays.copyOf(mLux, mLux.length), Arrays.copyOf(mNits, mNits.length)); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeFloatArray(mLux); + dest.writeFloatArray(mNits); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("BrightnessConfiguration{["); + final int size = mLux.length; + for (int i = 0; i < size; i++) { + if (i != 0) { + sb.append(", "); + } + sb.append("(").append(mLux[i]).append(", ").append(mNits[i]).append(")"); + } + sb.append("]}"); + return sb.toString(); + } + + @Override + public int hashCode() { + int result = 1; + result = result * 31 + Arrays.hashCode(mLux); + result = result * 31 + Arrays.hashCode(mNits); + return result; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof BrightnessConfiguration)) { + return false; + } + final BrightnessConfiguration other = (BrightnessConfiguration) o; + return Arrays.equals(mLux, other.mLux) && Arrays.equals(mNits, other.mNits); + } + + public static final Creator<BrightnessConfiguration> CREATOR = + new Creator<BrightnessConfiguration>() { + public BrightnessConfiguration createFromParcel(Parcel in) { + Builder builder = new Builder(); + float[] lux = in.createFloatArray(); + float[] nits = in.createFloatArray(); + builder.setCurve(lux, nits); + return builder.build(); + } + + public BrightnessConfiguration[] newArray(int size) { + return new BrightnessConfiguration[size]; + } + }; + + /** + * A builder class for {@link BrightnessConfiguration}s. + */ + public static class Builder { + private float[] mCurveLux; + private float[] mCurveNits; + + /** + * Sets the control points for the brightness curve. + * + * Brightness curves must have strictly increasing ambient brightness values in lux and + * monotonically increasing display brightness values in nits. In addition, the initial + * control point must be 0 lux. + * + * @throws IllegalArgumentException if the initial control point is not at 0 lux. + * @throws IllegalArgumentException if the lux levels are not strictly increasing. + * @throws IllegalArgumentException if the nit levels are not monotonically increasing. + */ + public Builder setCurve(float[] lux, float[] nits) { + Preconditions.checkNotNull(lux); + Preconditions.checkNotNull(nits); + if (lux.length == 0 || nits.length == 0) { + throw new IllegalArgumentException("Lux and nits arrays must not be empty"); + } + if (lux.length != nits.length) { + throw new IllegalArgumentException("Lux and nits arrays must be the same length"); + } + if (lux[0] != 0) { + throw new IllegalArgumentException("Initial control point must be for 0 lux"); + } + Preconditions.checkArrayElementsInRange(lux, 0, Float.MAX_VALUE, "lux"); + Preconditions.checkArrayElementsInRange(nits, 0, Float.MAX_VALUE, "nits"); + checkMonotonic(lux, true/*strictly increasing*/, "lux"); + checkMonotonic(nits, false /*strictly increasing*/, "nits"); + mCurveLux = lux; + mCurveNits = nits; + return this; + } + + /** + * Builds the {@link BrightnessConfiguration}. + * + * A brightness curve <b>must</b> be set before calling this. + */ + public BrightnessConfiguration build() { + if (mCurveLux == null || mCurveNits == null) { + throw new IllegalStateException("A curve must be set!"); + } + return new BrightnessConfiguration(mCurveLux, mCurveNits); + } + + private static void checkMonotonic(float[] vals, boolean strictlyIncreasing, String name) { + if (vals.length <= 1) { + return; + } + float prev = vals[0]; + for (int i = 1; i < vals.length; i++) { + if (prev > vals[i] || prev == vals[i] && strictlyIncreasing) { + String condition = strictlyIncreasing ? "strictly increasing" : "monotonic"; + throw new IllegalArgumentException(name + " values must be " + condition); + } + prev = vals[i]; + } + } + } +} diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 97ca231bf68c..7de667dcaa2b 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -27,6 +27,7 @@ import android.content.Context; import android.graphics.Point; import android.media.projection.MediaProjection; import android.os.Handler; +import android.os.UserHandle; import android.util.SparseArray; import android.view.Display; import android.view.Surface; @@ -634,6 +635,27 @@ public final class DisplayManager { } /** + * Sets the global display brightness configuration. + * + * @hide + */ + public void setBrightnessConfiguration(BrightnessConfiguration c) { + setBrightnessConfigurationForUser(c, UserHandle.myUserId()); + } + + /** + * Sets the global display brightness configuration for a specific user. + * + * Note this requires the INTERACT_ACROSS_USERS permission if setting the configuration for a + * user other than the one you're currently running as. + * + * @hide + */ + public void setBrightnessConfigurationForUser(BrightnessConfiguration c, int userId) { + mGlobal.setBrightnessConfigurationForUser(c, userId); + } + + /** * Listens for changes in available display devices. */ public interface DisplayListener { diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java index c3f82f56dad8..bf4cc1d826a9 100644 --- a/core/java/android/hardware/display/DisplayManagerGlobal.java +++ b/core/java/android/hardware/display/DisplayManagerGlobal.java @@ -487,6 +487,19 @@ public final class DisplayManagerGlobal { } } + /** + * Sets the global brightness configuration for a given user. + * + * @hide + */ + public void setBrightnessConfigurationForUser(BrightnessConfiguration c, int userId) { + try { + mDm.setBrightnessConfigurationForUser(c, userId); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + } + private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub { @Override public void onDisplayEvent(int displayId, int event) { diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl index f2ed9e7571d3..8afae6ec9010 100644 --- a/core/java/android/hardware/display/IDisplayManager.aidl +++ b/core/java/android/hardware/display/IDisplayManager.aidl @@ -18,6 +18,7 @@ package android.hardware.display; import android.content.pm.ParceledListSlice; import android.graphics.Point; +import android.hardware.display.BrightnessConfiguration; import android.hardware.display.IDisplayManagerCallback; import android.hardware.display.IVirtualDisplayCallback; import android.hardware.display.WifiDisplay; @@ -89,4 +90,9 @@ interface IDisplayManager { // STOPSHIP remove when adaptive brightness code is updated to accept curves. // Requires BRIGHTNESS_SLIDER_USAGE permission. void setBrightness(int brightness); + + // Sets the global brightness configuration for a given user. Requires + // CONFIGURE_DISPLAY_BRIGHTNESS, and INTERACT_ACROSS_USER if the user being configured is not + // the same as the calling user. + void setBrightnessConfigurationForUser(in BrightnessConfiguration c, int userId); } diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java index b31c7bcdb31e..1d66dc6d939f 100644 --- a/core/java/android/hardware/location/ContextHubManager.java +++ b/core/java/android/hardware/location/ContextHubManager.java @@ -342,7 +342,17 @@ public final class ContextHubManager { @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public ContextHubTransaction<Void> loadNanoApp( ContextHubInfo hubInfo, NanoAppBinary appBinary) { - throw new UnsupportedOperationException("TODO: Implement this"); + ContextHubTransaction<Void> transaction = + new ContextHubTransaction<>(ContextHubTransaction.TYPE_LOAD_NANOAPP); + IContextHubTransactionCallback callback = createTransactionCallback(transaction); + + try { + mService.loadNanoAppOnHub(hubInfo.getId(), callback, appBinary); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + return transaction; } /** @@ -357,7 +367,17 @@ public final class ContextHubManager { */ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public ContextHubTransaction<Void> unloadNanoApp(ContextHubInfo hubInfo, long nanoAppId) { - throw new UnsupportedOperationException("TODO: Implement this"); + ContextHubTransaction<Void> transaction = + new ContextHubTransaction<>(ContextHubTransaction.TYPE_UNLOAD_NANOAPP); + IContextHubTransactionCallback callback = createTransactionCallback(transaction); + + try { + mService.unloadNanoAppFromHub(hubInfo.getId(), callback, nanoAppId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + return transaction; } /** @@ -401,7 +421,17 @@ public final class ContextHubManager { */ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public ContextHubTransaction<List<NanoAppState>> queryNanoApps(ContextHubInfo hubInfo) { - throw new UnsupportedOperationException("TODO: Implement this"); + ContextHubTransaction<List<NanoAppState>> transaction = + new ContextHubTransaction<>(ContextHubTransaction.TYPE_QUERY_NANOAPPS); + IContextHubTransactionCallback callback = createQueryCallback(transaction); + + try { + mService.queryNanoApps(hubInfo.getId(), callback); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + return transaction; } /** diff --git a/core/java/android/hardware/location/ContextHubTransaction.java b/core/java/android/hardware/location/ContextHubTransaction.java index a8569ef479a1..b808de3a11d6 100644 --- a/core/java/android/hardware/location/ContextHubTransaction.java +++ b/core/java/android/hardware/location/ContextHubTransaction.java @@ -72,7 +72,8 @@ public class ContextHubTransaction<T> { TRANSACTION_FAILED_PENDING, TRANSACTION_FAILED_AT_HUB, TRANSACTION_FAILED_TIMEOUT, - TRANSACTION_FAILED_SERVICE_INTERNAL_FAILURE}) + TRANSACTION_FAILED_SERVICE_INTERNAL_FAILURE, + TRANSACTION_FAILED_HAL_UNAVAILABLE}) public @interface Result {} public static final int TRANSACTION_SUCCESS = 0; /** @@ -103,6 +104,10 @@ public class ContextHubTransaction<T> { * Failure mode when the transaction has failed internally at the service. */ public static final int TRANSACTION_FAILED_SERVICE_INTERNAL_FAILURE = 7; + /** + * Failure mode when the Context Hub HAL was not available. + */ + public static final int TRANSACTION_FAILED_HAL_UNAVAILABLE = 8; /** * A class describing the response for a ContextHubTransaction. @@ -189,6 +194,30 @@ public class ContextHubTransaction<T> { } /** + * Converts a transaction type to a human-readable string + * + * @param type the type of a transaction + * @param upperCase {@code true} if upper case the first letter, {@code false} otherwise + * @return a string describing the transaction + */ + public static String typeToString(@Type int type, boolean upperCase) { + switch (type) { + case ContextHubTransaction.TYPE_LOAD_NANOAPP: + return upperCase ? "Load" : "load"; + case ContextHubTransaction.TYPE_UNLOAD_NANOAPP: + return upperCase ? "Unload" : "unload"; + case ContextHubTransaction.TYPE_ENABLE_NANOAPP: + return upperCase ? "Enable" : "enable"; + case ContextHubTransaction.TYPE_DISABLE_NANOAPP: + return upperCase ? "Disable" : "disable"; + case ContextHubTransaction.TYPE_QUERY_NANOAPPS: + return upperCase ? "Query" : "query"; + default: + return upperCase ? "Unknown" : "unknown"; + } + } + + /** * @return the type of the transaction */ @Type @@ -239,7 +268,7 @@ public class ContextHubTransaction<T> { * A transaction can be invalidated if the process owning the transaction is no longer active * and the reference to this object is lost. * - * This method or {@link #setCallbackOnCompletecan(ContextHubTransaction.Callback)} can only be + * This method or {@link #setCallbackOnComplete(ContextHubTransaction.Callback)} can only be * invoked once, or an IllegalStateException will be thrown. * * @param callback the callback to be invoked upon completion diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl index 1bb7c8fbb6e7..628ebc7d4579 100644 --- a/core/java/android/hardware/location/IContextHubService.aidl +++ b/core/java/android/hardware/location/IContextHubService.aidl @@ -20,41 +20,56 @@ package android.hardware.location; import android.hardware.location.ContextHubInfo; import android.hardware.location.ContextHubMessage; import android.hardware.location.NanoApp; +import android.hardware.location.NanoAppBinary; import android.hardware.location.NanoAppFilter; import android.hardware.location.NanoAppInstanceInfo; import android.hardware.location.IContextHubCallback; import android.hardware.location.IContextHubClient; import android.hardware.location.IContextHubClientCallback; +import android.hardware.location.IContextHubTransactionCallback; /** * @hide */ interface IContextHubService { - // register a callback to receive messages + // Registers a callback to receive messages int registerCallback(in IContextHubCallback callback); // Gets a list of available context hub handles int[] getContextHubHandles(); - // Get the properties of a hub + // Gets the properties of a hub ContextHubInfo getContextHubInfo(int contextHubHandle); - // Load a nanoapp on a specified context hub + // Loads a nanoapp at the specified hub (old API) int loadNanoApp(int hubHandle, in NanoApp app); - // Unload a nanoapp instance + // Unloads a nanoapp given its instance ID (old API) int unloadNanoApp(int nanoAppInstanceHandle); - // get information about a nanoAppInstance + // Gets the NanoAppInstanceInfo of a nanoapp give its instance ID NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle); - // find all nanoApp instances matching some filter + // Finds all nanoApp instances matching some filter int[] findNanoAppOnHub(int hubHandle, in NanoAppFilter filter); - // send a message to a nanoApp + // Sends a message to a nanoApp int sendMessage(int hubHandle, int nanoAppHandle, in ContextHubMessage msg); // Creates a client to send and receive messages IContextHubClient createClient(in IContextHubClientCallback client, int contextHubId); + + // Loads a nanoapp at the specified hub (new API) + void loadNanoAppOnHub( + int contextHubId, in IContextHubTransactionCallback transactionCallback, + in NanoAppBinary nanoAppBinary); + + // Unloads a nanoapp on a specified context hub (new API) + void unloadNanoAppFromHub( + int contextHubId, in IContextHubTransactionCallback transactionCallback, + long nanoAppId); + + // Queries for a list of nanoapps + void queryNanoApps(int contextHubId, in IContextHubTransactionCallback transactionCallback); } diff --git a/core/java/android/net/metrics/DefaultNetworkEvent.java b/core/java/android/net/metrics/DefaultNetworkEvent.java index 8ff8e4f38d6d..6f383b4d515b 100644 --- a/core/java/android/net/metrics/DefaultNetworkEvent.java +++ b/core/java/android/net/metrics/DefaultNetworkEvent.java @@ -74,7 +74,7 @@ public class DefaultNetworkEvent { j.add("final_score=" + finalScore); } j.add(String.format("duration=%.0fs", durationMs / 1000.0)); - j.add(String.format("validation=%4.1f%%", (validatedMs * 100.0) / durationMs)); + j.add(String.format("validation=%04.1f%%", (validatedMs * 100.0) / durationMs)); return j.toString(); } diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 948d4cec1003..2e9eeb16a887 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -6742,7 +6742,7 @@ public abstract class BatteryStats implements Parcelable { /** Dump #STATS_SINCE_CHARGED batterystats data to a proto. @hide */ public void dumpProtoLocked(Context context, FileDescriptor fd, List<ApplicationInfo> apps, - int flags, long historyStart) { + int flags) { final ProtoOutputStream proto = new ProtoOutputStream(fd); final long bToken = proto.start(BatteryStatsServiceDumpProto.BATTERYSTATS); prepareForDumpLocked(); @@ -6752,13 +6752,7 @@ public abstract class BatteryStats implements Parcelable { proto.write(BatteryStatsProto.START_PLATFORM_VERSION, getStartPlatformVersion()); proto.write(BatteryStatsProto.END_PLATFORM_VERSION, getEndPlatformVersion()); - long now = getHistoryBaseTime() + SystemClock.elapsedRealtime(); - - if ((flags & (DUMP_INCLUDE_HISTORY | DUMP_HISTORY_ONLY)) != 0) { - if (startIteratingHistoryLocked()) { - // TODO: implement dumpProtoHistoryLocked(proto); - } - } + // History intentionally not included in proto dump. if ((flags & (DUMP_HISTORY_ONLY | DUMP_DAILY_ONLY)) == 0) { final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index c1722d54c541..48f56847e88d 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -221,13 +221,31 @@ public class Build { public static final String SDK = getString("ro.build.version.sdk"); /** - * The user-visible SDK version of the framework; its possible - * values are defined in {@link Build.VERSION_CODES}. + * The SDK version of the software currently running on this hardware + * device. This value never changes while a device is booted, but it may + * increase when the hardware manufacturer provides an OTA update. + * <p> + * Possible values are defined in {@link Build.VERSION_CODES}. + * + * @see #FIRST_SDK_INT */ public static final int SDK_INT = SystemProperties.getInt( "ro.build.version.sdk", 0); /** + * The SDK version of the software that <em>initially</em> shipped on + * this hardware device. It <em>never</em> changes during the lifetime + * of the device, even when {@link #SDK_INT} increases due to an OTA + * update. + * <p> + * Possible values are defined in {@link Build.VERSION_CODES}. + * + * @see #SDK_INT + */ + public static final int FIRST_SDK_INT = SystemProperties + .getInt("ro.product.first_api_level", 0); + + /** * The developer preview revision of a prerelease SDK. This value will always * be <code>0</code> on production platform builds/devices. * @@ -270,6 +288,14 @@ public class Build { * @hide */ public static final int RESOURCES_SDK_INT = SDK_INT + ACTIVE_CODENAMES.length; + + /** + * The current lowest supported value of app target SDK. Applications targeting + * lower values will fail to install and run. Its possible values are defined + * in {@link Build.VERSION_CODES}. + */ + public static final int MIN_SUPPORTED_TARGET_SDK_INT = SystemProperties.getInt( + "ro.build.version.min_supported_target_sdk", 0); } /** diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java index 9369eebfd984..6c9f1b25bf66 100644 --- a/core/java/android/os/UserManagerInternal.java +++ b/core/java/android/os/UserManagerInternal.java @@ -130,7 +130,8 @@ public abstract class UserManagerInternal { * <p>Called by the {@link com.android.server.devicepolicy.DevicePolicyManagerService} when * createAndManageUser is called by the device owner. */ - public abstract UserInfo createUserEvenWhenDisallowed(String name, int flags); + public abstract UserInfo createUserEvenWhenDisallowed(String name, int flags, + String[] disallowedPackages); /** * Same as {@link UserManager#removeUser(int userHandle)}, but bypasses the check for diff --git a/core/java/android/text/PremeasuredText.java b/core/java/android/text/PremeasuredText.java new file mode 100644 index 000000000000..465314dd21ac --- /dev/null +++ b/core/java/android/text/PremeasuredText.java @@ -0,0 +1,272 @@ +/* + * 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.text; + +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.util.IntArray; + +import com.android.internal.util.ArrayUtils; +import com.android.internal.util.Preconditions; + +import java.util.ArrayList; + +/** + * A text which has already been measured. + * + * TODO: Rename to better name? e.g. MeasuredText, FrozenText etc. + */ +public class PremeasuredText implements Spanned { + private static final char LINE_FEED = '\n'; + + // The original text. + private final @NonNull CharSequence mText; + + // The inclusive start offset of the measuring target. + private final @IntRange(from = 0) int mStart; + + // The exclusive end offset of the measuring target. + private final @IntRange(from = 0) int mEnd; + + // The TextPaint used for measurement. + private final @NonNull TextPaint mPaint; + + // The requested text direction. + private final @NonNull TextDirectionHeuristic mTextDir; + + // The measured paragraph texts. + private final @NonNull MeasuredText[] mMeasuredTexts; + + // The sorted paragraph end offsets. + private final @NonNull int[] mParagraphBreakPoints; + + /** + * Build PremeasuredText from the text. + * + * @param text The text to be measured. + * @param paint The paint to be used for drawing. + * @param textDir The text direction. + * @return The measured text. + */ + public static @NonNull PremeasuredText build(@NonNull CharSequence text, + @NonNull TextPaint paint, + @NonNull TextDirectionHeuristic textDir) { + return PremeasuredText.build(text, paint, textDir, 0, text.length()); + } + + /** + * Build PremeasuredText from the specific range of the text.. + * + * @param text The text to be measured. + * @param paint The paint to be used for drawing. + * @param textDir The text direction. + * @param start The inclusive start offset of the text. + * @param end The exclusive start offset of the text. + * @return The measured text. + */ + public static @NonNull PremeasuredText build(@NonNull CharSequence text, + @NonNull TextPaint paint, + @NonNull TextDirectionHeuristic textDir, + @IntRange(from = 0) int start, + @IntRange(from = 0) int end) { + Preconditions.checkNotNull(text); + Preconditions.checkNotNull(paint); + Preconditions.checkNotNull(textDir); + Preconditions.checkArgumentInRange(start, 0, text.length(), "start"); + Preconditions.checkArgumentInRange(end, 0, text.length(), "end"); + + final IntArray paragraphEnds = new IntArray(); + final ArrayList<MeasuredText> measuredTexts = new ArrayList<>(); + + int paraEnd = 0; + for (int paraStart = start; paraStart < end; paraStart = paraEnd) { + paraEnd = TextUtils.indexOf(text, LINE_FEED, paraStart, end); + if (paraEnd < 0) { + // No LINE_FEED(U+000A) character found. Use end of the text as the paragraph end. + paraEnd = end; + } else { + paraEnd++; // Includes LINE_FEED(U+000A) to the prev paragraph. + } + + paragraphEnds.add(paraEnd); + measuredTexts.add(MeasuredText.buildForStaticLayout( + paint, text, paraStart, paraEnd, textDir, null /* no recycle */)); + } + + return new PremeasuredText(text, start, end, paint, textDir, + measuredTexts.toArray(new MeasuredText[measuredTexts.size()]), + paragraphEnds.toArray()); + } + + // Use PremeasuredText.build instead. + private PremeasuredText(@NonNull CharSequence text, + @IntRange(from = 0) int start, + @IntRange(from = 0) int end, + @NonNull TextPaint paint, + @NonNull TextDirectionHeuristic textDir, + @NonNull MeasuredText[] measuredTexts, + @NonNull int[] paragraphBreakPoints) { + mText = text; + mStart = start; + mEnd = end; + mPaint = paint; + mMeasuredTexts = measuredTexts; + mParagraphBreakPoints = paragraphBreakPoints; + mTextDir = textDir; + } + + /** + * Return the underlying text. + */ + public @NonNull CharSequence getText() { + return mText; + } + + /** + * Returns the inclusive start offset of measured region. + */ + public @IntRange(from = 0) int getStart() { + return mStart; + } + + /** + * Returns the exclusive end offset of measured region. + */ + public @IntRange(from = 0) int getEnd() { + return mEnd; + } + + /** + * Returns the text direction associated with char sequence. + */ + public @NonNull TextDirectionHeuristic getTextDir() { + return mTextDir; + } + + /** + * Returns the paint used to measure this text. + */ + public @NonNull TextPaint getPaint() { + return mPaint; + } + + /** + * Returns the length of the paragraph of this text. + */ + public @IntRange(from = 0) int getParagraphCount() { + return mParagraphBreakPoints.length; + } + + /** + * Returns the paragraph start offset of the text. + */ + public @IntRange(from = 0) int getParagraphStart(@IntRange(from = 0) int paraIndex) { + Preconditions.checkArgumentInRange(paraIndex, 0, getParagraphCount(), "paraIndex"); + return paraIndex == 0 ? mStart : mParagraphBreakPoints[paraIndex - 1]; + } + + /** + * Returns the paragraph end offset of the text. + */ + public @IntRange(from = 0) int getParagraphEnd(@IntRange(from = 0) int paraIndex) { + Preconditions.checkArgumentInRange(paraIndex, 0, getParagraphCount(), "paraIndex"); + return mParagraphBreakPoints[paraIndex]; + } + + /** @hide */ + public @NonNull MeasuredText getMeasuredText(@IntRange(from = 0) int paraIndex) { + return mMeasuredTexts[paraIndex]; + } + + /////////////////////////////////////////////////////////////////////////////////////////////// + // Spanned overrides + // + // Just proxy for underlying mText if appropriate. + + @Override + public <T> T[] getSpans(int start, int end, Class<T> type) { + if (mText instanceof Spanned) { + return ((Spanned) mText).getSpans(start, end, type); + } else { + return ArrayUtils.emptyArray(type); + } + } + + @Override + public int getSpanStart(Object tag) { + if (mText instanceof Spanned) { + return ((Spanned) mText).getSpanStart(tag); + } else { + return -1; + } + } + + @Override + public int getSpanEnd(Object tag) { + if (mText instanceof Spanned) { + return ((Spanned) mText).getSpanEnd(tag); + } else { + return -1; + } + } + + @Override + public int getSpanFlags(Object tag) { + if (mText instanceof Spanned) { + return ((Spanned) mText).getSpanFlags(tag); + } else { + return 0; + } + } + + @Override + public int nextSpanTransition(int start, int limit, Class type) { + if (mText instanceof Spanned) { + return ((Spanned) mText).nextSpanTransition(start, limit, type); + } else { + return mText.length(); + } + } + + /////////////////////////////////////////////////////////////////////////////////////////////// + // CharSequence overrides. + // + // Just proxy for underlying mText. + + @Override + public int length() { + return mText.length(); + } + + @Override + public char charAt(int index) { + // TODO: Should this be index + mStart ? + return mText.charAt(index); + } + + @Override + public CharSequence subSequence(int start, int end) { + // TODO: return PremeasuredText. + // TODO: Should this be index + mStart, end + mStart ? + return mText.subSequence(start, end); + } + + @Override + public String toString() { + return mText.toString(); + } +} diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index 400b075d889d..2e10fe8d4267 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -610,8 +610,8 @@ public class StaticLayout extends Layout { /* package */ void generate(Builder b, boolean includepad, boolean trackpad) { final CharSequence source = b.mText; - int bufStart = b.mStart; - int bufEnd = b.mEnd; + final int bufStart = b.mStart; + final int bufEnd = b.mEnd; TextPaint paint = b.mPaint; int outerWidth = b.mWidth; TextDirectionHeuristic textDir = b.mTextDir; @@ -634,10 +634,6 @@ public class StaticLayout extends Layout { Paint.FontMetricsInt fm = b.mFontMetricsInt; int[] chooseHtv = null; - Spanned spanned = null; - if (source instanceof Spanned) - spanned = (Spanned) source; - final int[] indents; if (mLeftIndents != null || mRightIndents != null) { final int leftLen = mLeftIndents == null ? 0 : mLeftIndents.length; @@ -660,16 +656,34 @@ public class StaticLayout extends Layout { b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE, indents, mLeftPaddings, mRightPaddings); - MeasuredText measured = null; + PremeasuredText premeasured = null; + final Spanned spanned; + if (source instanceof PremeasuredText) { + premeasured = (PremeasuredText) source; + + final CharSequence original = premeasured.getText(); + spanned = (original instanceof Spanned) ? (Spanned) original : null; + + if (bufStart != premeasured.getStart() || bufEnd != premeasured.getEnd()) { + // The buffer position has changed. Re-measure here. + premeasured = PremeasuredText.build(original, paint, textDir, bufStart, bufEnd); + } else { + // We can use premeasured information. + + // Overwrite with the one when premeasured. + // TODO: Give an option for developer not to overwrite and measure again here? + textDir = premeasured.getTextDir(); + paint = premeasured.getPaint(); + } + } else { + premeasured = PremeasuredText.build(source, paint, textDir, bufStart, bufEnd); + spanned = (source instanceof Spanned) ? (Spanned) source : null; + } + try { - int paraEnd; - for (int paraStart = bufStart; paraStart <= bufEnd; paraStart = paraEnd) { - paraEnd = TextUtils.indexOf(source, CHAR_NEW_LINE, paraStart, bufEnd); - if (paraEnd < 0) { - paraEnd = bufEnd; - } else { - paraEnd++; - } + for (int paraIndex = 0; paraIndex < premeasured.getParagraphCount(); paraIndex++) { + final int paraStart = premeasured.getParagraphStart(paraIndex); + final int paraEnd = premeasured.getParagraphEnd(paraIndex); int firstWidthLineCount = 1; int firstWidth = outerWidth; @@ -735,8 +749,7 @@ public class StaticLayout extends Layout { } } - measured = MeasuredText.buildForStaticLayout( - paint, source, paraStart, paraEnd, textDir, measured); + final MeasuredText measured = premeasured.getMeasuredText(paraIndex); final char[] chs = measured.getChars(); final int[] spanEndCache = measured.getSpanEndCache().getRawArray(); final int[] fmCache = measured.getFontMetrics().getRawArray(); @@ -887,6 +900,8 @@ public class StaticLayout extends Layout { if ((bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE) && mLineCount < mMaximumVisibleLineCount) { + final MeasuredText measured = + MeasuredText.buildForBidi(source, bufEnd, bufEnd, textDir, null); paint.getFontMetricsInt(fm); v = out(source, bufEnd, bufEnd, fm.ascent, fm.descent, @@ -894,15 +909,12 @@ public class StaticLayout extends Layout { v, spacingmult, spacingadd, null, null, fm, 0, - needMultiply, null, bufEnd, + needMultiply, measured, bufEnd, includepad, trackpad, addLastLineSpacing, null, null, bufStart, ellipsize, ellipsizedWidth, 0, paint, false); } } finally { - if (measured != null) { - measured.recycle(); - } nFinish(nativePtr); } } @@ -912,7 +924,7 @@ public class StaticLayout extends Layout { private int out(final CharSequence text, final int start, final int end, int above, int below, int top, int bottom, int v, final float spacingmult, final float spacingadd, final LineHeightSpan[] chooseHt, final int[] chooseHtv, final Paint.FontMetricsInt fm, - final int flags, final boolean needMultiply, @Nullable final MeasuredText measured, + final int flags, final boolean needMultiply, @NonNull final MeasuredText measured, final int bufEnd, final boolean includePad, final boolean trackPad, final boolean addLastLineLineSpacing, final char[] chs, final float[] widths, final int widthStart, final TextUtils.TruncateAt ellipsize, final float ellipsisWidth, @@ -921,7 +933,7 @@ public class StaticLayout extends Layout { final int off = j * mColumns; final int want = off + mColumns + TOP; int[] lines = mLines; - final int dir = (start == end) ? Layout.DIR_LEFT_TO_RIGHT : measured.getParagraphDir(); + final int dir = measured.getParagraphDir(); if (want >= lines.length) { final int[] grow = ArrayUtils.newUnpaddedIntArray(GrowingArrayUtils.growSize(want)); @@ -948,11 +960,7 @@ public class StaticLayout extends Layout { lines[off + TAB] |= flags & TAB_MASK; lines[off + HYPHEN] = flags; lines[off + DIR] |= dir << DIR_SHIFT; - if (start == end) { - mLineDirections[j] = Layout.DIRS_ALL_LEFT_TO_RIGHT; - } else { - mLineDirections[j] = measured.getDirections(start - widthStart, end - widthStart); - } + mLineDirections[j] = measured.getDirections(start - widthStart, end - widthStart); final boolean firstLine = (j == 0); final boolean currentLineIsTheLastVisibleOne = (j + 1 == mMaximumVisibleLineCount); diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java index 52e53b074165..bc2953e0c0fe 100644 --- a/core/java/android/view/GestureDetector.java +++ b/core/java/android/view/GestureDetector.java @@ -520,162 +520,163 @@ public class GestureDetector { boolean handled = false; switch (action & MotionEvent.ACTION_MASK) { - case MotionEvent.ACTION_POINTER_DOWN: - mDownFocusX = mLastFocusX = focusX; - mDownFocusY = mLastFocusY = focusY; - // Cancel long press and taps - cancelTaps(); - break; - - case MotionEvent.ACTION_POINTER_UP: - mDownFocusX = mLastFocusX = focusX; - mDownFocusY = mLastFocusY = focusY; - - // Check the dot product of current velocities. - // If the pointer that left was opposing another velocity vector, clear. - mVelocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity); - final int upIndex = ev.getActionIndex(); - final int id1 = ev.getPointerId(upIndex); - final float x1 = mVelocityTracker.getXVelocity(id1); - final float y1 = mVelocityTracker.getYVelocity(id1); - for (int i = 0; i < count; i++) { - if (i == upIndex) continue; - - final int id2 = ev.getPointerId(i); - final float x = x1 * mVelocityTracker.getXVelocity(id2); - final float y = y1 * mVelocityTracker.getYVelocity(id2); - - final float dot = x + y; - if (dot < 0) { - mVelocityTracker.clear(); - break; + case MotionEvent.ACTION_POINTER_DOWN: + mDownFocusX = mLastFocusX = focusX; + mDownFocusY = mLastFocusY = focusY; + // Cancel long press and taps + cancelTaps(); + break; + + case MotionEvent.ACTION_POINTER_UP: + mDownFocusX = mLastFocusX = focusX; + mDownFocusY = mLastFocusY = focusY; + + // Check the dot product of current velocities. + // If the pointer that left was opposing another velocity vector, clear. + mVelocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity); + final int upIndex = ev.getActionIndex(); + final int id1 = ev.getPointerId(upIndex); + final float x1 = mVelocityTracker.getXVelocity(id1); + final float y1 = mVelocityTracker.getYVelocity(id1); + for (int i = 0; i < count; i++) { + if (i == upIndex) continue; + + final int id2 = ev.getPointerId(i); + final float x = x1 * mVelocityTracker.getXVelocity(id2); + final float y = y1 * mVelocityTracker.getYVelocity(id2); + + final float dot = x + y; + if (dot < 0) { + mVelocityTracker.clear(); + break; + } } - } - break; - - case MotionEvent.ACTION_DOWN: - if (mDoubleTapListener != null) { - boolean hadTapMessage = mHandler.hasMessages(TAP); - if (hadTapMessage) mHandler.removeMessages(TAP); - if ((mCurrentDownEvent != null) && (mPreviousUpEvent != null) && hadTapMessage && - isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev)) { - // This is a second tap - mIsDoubleTapping = true; - // Give a callback with the first tap of the double-tap - handled |= mDoubleTapListener.onDoubleTap(mCurrentDownEvent); - // Give a callback with down event of the double-tap - handled |= mDoubleTapListener.onDoubleTapEvent(ev); - } else { - // This is a first tap - mHandler.sendEmptyMessageDelayed(TAP, DOUBLE_TAP_TIMEOUT); + break; + + case MotionEvent.ACTION_DOWN: + if (mDoubleTapListener != null) { + boolean hadTapMessage = mHandler.hasMessages(TAP); + if (hadTapMessage) mHandler.removeMessages(TAP); + if ((mCurrentDownEvent != null) && (mPreviousUpEvent != null) + && hadTapMessage + && isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev)) { + // This is a second tap + mIsDoubleTapping = true; + // Give a callback with the first tap of the double-tap + handled |= mDoubleTapListener.onDoubleTap(mCurrentDownEvent); + // Give a callback with down event of the double-tap + handled |= mDoubleTapListener.onDoubleTapEvent(ev); + } else { + // This is a first tap + mHandler.sendEmptyMessageDelayed(TAP, DOUBLE_TAP_TIMEOUT); + } } - } - mDownFocusX = mLastFocusX = focusX; - mDownFocusY = mLastFocusY = focusY; - if (mCurrentDownEvent != null) { - mCurrentDownEvent.recycle(); - } - mCurrentDownEvent = MotionEvent.obtain(ev); - mAlwaysInTapRegion = true; - mAlwaysInBiggerTapRegion = true; - mStillDown = true; - mInLongPress = false; - mDeferConfirmSingleTap = false; - - if (mIsLongpressEnabled) { - mHandler.removeMessages(LONG_PRESS); - mHandler.sendEmptyMessageAtTime(LONG_PRESS, - mCurrentDownEvent.getDownTime() + LONGPRESS_TIMEOUT); - } - mHandler.sendEmptyMessageAtTime(SHOW_PRESS, - mCurrentDownEvent.getDownTime() + TAP_TIMEOUT); - handled |= mListener.onDown(ev); - break; + mDownFocusX = mLastFocusX = focusX; + mDownFocusY = mLastFocusY = focusY; + if (mCurrentDownEvent != null) { + mCurrentDownEvent.recycle(); + } + mCurrentDownEvent = MotionEvent.obtain(ev); + mAlwaysInTapRegion = true; + mAlwaysInBiggerTapRegion = true; + mStillDown = true; + mInLongPress = false; + mDeferConfirmSingleTap = false; - case MotionEvent.ACTION_MOVE: - if (mInLongPress || mInContextClick) { + if (mIsLongpressEnabled) { + mHandler.removeMessages(LONG_PRESS); + mHandler.sendEmptyMessageAtTime(LONG_PRESS, + mCurrentDownEvent.getDownTime() + LONGPRESS_TIMEOUT); + } + mHandler.sendEmptyMessageAtTime(SHOW_PRESS, + mCurrentDownEvent.getDownTime() + TAP_TIMEOUT); + handled |= mListener.onDown(ev); break; - } - final float scrollX = mLastFocusX - focusX; - final float scrollY = mLastFocusY - focusY; - if (mIsDoubleTapping) { - // Give the move events of the double-tap - handled |= mDoubleTapListener.onDoubleTapEvent(ev); - } else if (mAlwaysInTapRegion) { - final int deltaX = (int) (focusX - mDownFocusX); - final int deltaY = (int) (focusY - mDownFocusY); - int distance = (deltaX * deltaX) + (deltaY * deltaY); - int slopSquare = isGeneratedGesture ? 0 : mTouchSlopSquare; - if (distance > slopSquare) { + + case MotionEvent.ACTION_MOVE: + if (mInLongPress || mInContextClick) { + break; + } + final float scrollX = mLastFocusX - focusX; + final float scrollY = mLastFocusY - focusY; + if (mIsDoubleTapping) { + // Give the move events of the double-tap + handled |= mDoubleTapListener.onDoubleTapEvent(ev); + } else if (mAlwaysInTapRegion) { + final int deltaX = (int) (focusX - mDownFocusX); + final int deltaY = (int) (focusY - mDownFocusY); + int distance = (deltaX * deltaX) + (deltaY * deltaY); + int slopSquare = isGeneratedGesture ? 0 : mTouchSlopSquare; + if (distance > slopSquare) { + handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY); + mLastFocusX = focusX; + mLastFocusY = focusY; + mAlwaysInTapRegion = false; + mHandler.removeMessages(TAP); + mHandler.removeMessages(SHOW_PRESS); + mHandler.removeMessages(LONG_PRESS); + } + int doubleTapSlopSquare = isGeneratedGesture ? 0 : mDoubleTapTouchSlopSquare; + if (distance > doubleTapSlopSquare) { + mAlwaysInBiggerTapRegion = false; + } + } else if ((Math.abs(scrollX) >= 1) || (Math.abs(scrollY) >= 1)) { handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY); mLastFocusX = focusX; mLastFocusY = focusY; - mAlwaysInTapRegion = false; - mHandler.removeMessages(TAP); - mHandler.removeMessages(SHOW_PRESS); - mHandler.removeMessages(LONG_PRESS); } - int doubleTapSlopSquare = isGeneratedGesture ? 0 : mDoubleTapTouchSlopSquare; - if (distance > doubleTapSlopSquare) { - mAlwaysInBiggerTapRegion = false; + break; + + case MotionEvent.ACTION_UP: + mStillDown = false; + MotionEvent currentUpEvent = MotionEvent.obtain(ev); + if (mIsDoubleTapping) { + // Finally, give the up event of the double-tap + handled |= mDoubleTapListener.onDoubleTapEvent(ev); + } else if (mInLongPress) { + mHandler.removeMessages(TAP); + mInLongPress = false; + } else if (mAlwaysInTapRegion && !mIgnoreNextUpEvent) { + handled = mListener.onSingleTapUp(ev); + if (mDeferConfirmSingleTap && mDoubleTapListener != null) { + mDoubleTapListener.onSingleTapConfirmed(ev); + } + } else if (!mIgnoreNextUpEvent) { + + // A fling must travel the minimum tap distance + final VelocityTracker velocityTracker = mVelocityTracker; + final int pointerId = ev.getPointerId(0); + velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity); + final float velocityY = velocityTracker.getYVelocity(pointerId); + final float velocityX = velocityTracker.getXVelocity(pointerId); + + if ((Math.abs(velocityY) > mMinimumFlingVelocity) + || (Math.abs(velocityX) > mMinimumFlingVelocity)) { + handled = mListener.onFling(mCurrentDownEvent, ev, velocityX, velocityY); + } } - } else if ((Math.abs(scrollX) >= 1) || (Math.abs(scrollY) >= 1)) { - handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY); - mLastFocusX = focusX; - mLastFocusY = focusY; - } - break; - - case MotionEvent.ACTION_UP: - mStillDown = false; - MotionEvent currentUpEvent = MotionEvent.obtain(ev); - if (mIsDoubleTapping) { - // Finally, give the up event of the double-tap - handled |= mDoubleTapListener.onDoubleTapEvent(ev); - } else if (mInLongPress) { - mHandler.removeMessages(TAP); - mInLongPress = false; - } else if (mAlwaysInTapRegion && !mIgnoreNextUpEvent) { - handled = mListener.onSingleTapUp(ev); - if (mDeferConfirmSingleTap && mDoubleTapListener != null) { - mDoubleTapListener.onSingleTapConfirmed(ev); + if (mPreviousUpEvent != null) { + mPreviousUpEvent.recycle(); } - } else if (!mIgnoreNextUpEvent) { - - // A fling must travel the minimum tap distance - final VelocityTracker velocityTracker = mVelocityTracker; - final int pointerId = ev.getPointerId(0); - velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity); - final float velocityY = velocityTracker.getYVelocity(pointerId); - final float velocityX = velocityTracker.getXVelocity(pointerId); - - if ((Math.abs(velocityY) > mMinimumFlingVelocity) - || (Math.abs(velocityX) > mMinimumFlingVelocity)){ - handled = mListener.onFling(mCurrentDownEvent, ev, velocityX, velocityY); + // Hold the event we obtained above - listeners may have changed the original. + mPreviousUpEvent = currentUpEvent; + if (mVelocityTracker != null) { + // This may have been cleared when we called out to the + // application above. + mVelocityTracker.recycle(); + mVelocityTracker = null; } - } - if (mPreviousUpEvent != null) { - mPreviousUpEvent.recycle(); - } - // Hold the event we obtained above - listeners may have changed the original. - mPreviousUpEvent = currentUpEvent; - if (mVelocityTracker != null) { - // This may have been cleared when we called out to the - // application above. - mVelocityTracker.recycle(); - mVelocityTracker = null; - } - mIsDoubleTapping = false; - mDeferConfirmSingleTap = false; - mIgnoreNextUpEvent = false; - mHandler.removeMessages(SHOW_PRESS); - mHandler.removeMessages(LONG_PRESS); - break; - - case MotionEvent.ACTION_CANCEL: - cancel(); - break; + mIsDoubleTapping = false; + mDeferConfirmSingleTap = false; + mIgnoreNextUpEvent = false; + mHandler.removeMessages(SHOW_PRESS); + mHandler.removeMessages(LONG_PRESS); + break; + + case MotionEvent.ACTION_CANCEL: + cancel(); + break; } if (!handled && mInputEventConsistencyVerifier != null) { diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 8a7b44178a11..357b8d9d039b 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -1149,7 +1149,9 @@ public class SurfaceControl implements Parcelable { } /** - * Copy the current screen contents into a bitmap and return it. + * Copy the current screen contents into a hardware bitmap and return it. + * Note: If you want to modify the Bitmap in software, you will need to copy the Bitmap into + * a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)} * * CAVEAT: Versions of screenshot that return a {@link Bitmap} can * be extremely slow; avoid use unless absolutely necessary; prefer @@ -1174,7 +1176,7 @@ public class SurfaceControl implements Parcelable { * screenshots in its native portrait orientation by default, so this is * useful for returning screenshots that are independent of device * orientation. - * @return Returns a Bitmap containing the screen contents, or null + * @return Returns a hardware Bitmap containing the screen contents, or null * if an error occurs. Make sure to call Bitmap.recycle() as soon as * possible, once its content is not needed anymore. */ @@ -1202,7 +1204,7 @@ public class SurfaceControl implements Parcelable { } /** - * Like {@link SurfaceControl#screenshot(int, int, int, int, boolean)} but + * Like {@link SurfaceControl#screenshot(Rect, int, int, int, int, boolean, int)} but * includes all Surfaces in the screenshot. This will also update the orientation so it * sends the correct coordinates to SF based on the rotation value. * @@ -1259,7 +1261,7 @@ public class SurfaceControl implements Parcelable { } /** - * Captures a layer and its children into the provided {@link Surface}. + * Captures a layer and its children and returns a {@link GraphicBuffer} with the content. * * @param layerHandleToken The root layer to capture. * @param sourceCrop The portion of the root surface to capture; caller may pass in 'new diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 6d4998b05c48..c6c42faad6b0 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -20,6 +20,7 @@ import static android.view.Display.INVALID_DISPLAY; import static android.view.View.PFLAG_DRAW_ANIMATION; import static android.view.WindowCallbacks.RESIZE_MODE_DOCKED_DIVIDER; import static android.view.WindowCallbacks.RESIZE_MODE_FREEFORM; +import static android.view.WindowManager.LayoutParams.FLAG2_LAYOUT_IN_DISPLAY_CUTOUT_AREA; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL; @@ -142,10 +143,11 @@ public final class ViewRootImpl implements ViewParent, private static final boolean DEBUG_KEEP_SCREEN_ON = false || LOCAL_LOGV; /** - * Set to false if we do not want to use the multi threaded renderer. Note that by disabling + * Set to false if we do not want to use the multi threaded renderer even though + * threaded renderer (aka hardware renderering) is used. Note that by disabling * this, WindowCallbacks will not fire. */ - private static final boolean USE_MT_RENDERER = true; + private static final boolean MT_RENDERER_AVAILABLE = true; /** * Set this system property to true to force the view hierarchy to render @@ -302,6 +304,7 @@ public final class ViewRootImpl implements ViewParent, Rect mDirty; public boolean mIsAnimating; + private boolean mUseMTRenderer; private boolean mDragResizing; private boolean mInvalidateRootRequested; private int mResizeMode; @@ -548,18 +551,14 @@ public final class ViewRootImpl implements ViewParent, } public void addWindowCallbacks(WindowCallbacks callback) { - if (USE_MT_RENDERER) { - synchronized (mWindowCallbacks) { - mWindowCallbacks.add(callback); - } + synchronized (mWindowCallbacks) { + mWindowCallbacks.add(callback); } } public void removeWindowCallbacks(WindowCallbacks callback) { - if (USE_MT_RENDERER) { - synchronized (mWindowCallbacks) { - mWindowCallbacks.remove(callback); - } + synchronized (mWindowCallbacks) { + mWindowCallbacks.remove(callback); } } @@ -685,7 +684,17 @@ public final class ViewRootImpl implements ViewParent, // If the application owns the surface, don't enable hardware acceleration if (mSurfaceHolder == null) { + // While this is supposed to enable only, it can effectively disable + // the acceleration too. enableHardwareAcceleration(attrs); + final boolean useMTRenderer = MT_RENDERER_AVAILABLE + && mAttachInfo.mThreadedRenderer != null; + if (mUseMTRenderer != useMTRenderer) { + // Shouldn't be resizing, as it's done only in window setup, + // but end just in case. + endDragResizing(); + mUseMTRenderer = useMTRenderer; + } } boolean restore = false; @@ -1578,7 +1587,15 @@ public final class ViewRootImpl implements ViewParent, } void dispatchApplyInsets(View host) { - host.dispatchApplyWindowInsets(getWindowInsets(true /* forceConstruct */)); + WindowInsets insets = getWindowInsets(true /* forceConstruct */); + final boolean layoutInCutout = + (mWindowAttributes.flags2 & FLAG2_LAYOUT_IN_DISPLAY_CUTOUT_AREA) != 0; + if (!layoutInCutout) { + // Window is either not laid out in cutout or the status bar inset takes care of + // clearing the cutout, so we don't need to dispatch the cutout to the hierarchy. + insets = insets.consumeCutout(); + } + host.dispatchApplyWindowInsets(insets); } private static boolean shouldUseDisplaySize(final WindowManager.LayoutParams lp) { @@ -2088,7 +2105,7 @@ public final class ViewRootImpl implements ViewParent, endDragResizing(); } } - if (!USE_MT_RENDERER) { + if (!mUseMTRenderer) { if (dragResizing) { mCanvasOffsetX = mWinFrame.left; mCanvasOffsetY = mWinFrame.top; @@ -2726,8 +2743,10 @@ public final class ViewRootImpl implements ViewParent, @Override public void onPostDraw(DisplayListCanvas canvas) { drawAccessibilityFocusedDrawableIfNeeded(canvas); - for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { - mWindowCallbacks.get(i).onPostDraw(canvas); + if (mUseMTRenderer) { + for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { + mWindowCallbacks.get(i).onPostDraw(canvas); + } } } @@ -3058,7 +3077,8 @@ public final class ViewRootImpl implements ViewParent, return; } - if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) { + if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, + scalingRequired, dirty, surfaceInsets)) { return; } } @@ -3074,11 +3094,22 @@ public final class ViewRootImpl implements ViewParent, * @return true if drawing was successful, false if an error occurred */ private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff, - boolean scalingRequired, Rect dirty) { + boolean scalingRequired, Rect dirty, Rect surfaceInsets) { // Draw with software renderer. final Canvas canvas; + + // We already have the offset of surfaceInsets in xoff, yoff and dirty region, + // therefore we need to add it back when moving the dirty region. + int dirtyXOffset = xoff; + int dirtyYOffset = yoff; + if (surfaceInsets != null) { + dirtyXOffset += surfaceInsets.left; + dirtyYOffset += surfaceInsets.top; + } + try { + dirty.offset(-dirtyXOffset, -dirtyYOffset); final int left = dirty.left; final int top = dirty.top; final int right = dirty.right; @@ -3105,6 +3136,8 @@ public final class ViewRootImpl implements ViewParent, // kill stuff (or ourself) for no reason. mLayoutRequested = true; // ask wm for a new surface next time. return false; + } finally { + dirty.offset(dirtyXOffset, dirtyYOffset); // Reset to the original value. } try { @@ -6578,7 +6611,7 @@ public final class ViewRootImpl implements ViewParent, // Tell all listeners that we are resizing the window so that the chrome can get // updated as fast as possible on a separate thread, - if (mDragResizing) { + if (mDragResizing && mUseMTRenderer) { boolean fullscreen = frame.equals(backDropFrame); synchronized (mWindowCallbacks) { for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { @@ -7828,9 +7861,11 @@ public final class ViewRootImpl implements ViewParent, Rect stableInsets, int resizeMode) { if (!mDragResizing) { mDragResizing = true; - for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { - mWindowCallbacks.get(i).onWindowDragResizeStart(initialBounds, fullscreen, - systemInsets, stableInsets, resizeMode); + if (mUseMTRenderer) { + for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { + mWindowCallbacks.get(i).onWindowDragResizeStart( + initialBounds, fullscreen, systemInsets, stableInsets, resizeMode); + } } mFullRedrawNeeded = true; } @@ -7842,8 +7877,10 @@ public final class ViewRootImpl implements ViewParent, private void endDragResizing() { if (mDragResizing) { mDragResizing = false; - for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { - mWindowCallbacks.get(i).onWindowDragResizeEnd(); + if (mUseMTRenderer) { + for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { + mWindowCallbacks.get(i).onWindowDragResizeEnd(); + } } mFullRedrawNeeded = true; } @@ -7851,19 +7888,21 @@ public final class ViewRootImpl implements ViewParent, private boolean updateContentDrawBounds() { boolean updated = false; - for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { - updated |= mWindowCallbacks.get(i).onContentDrawn( - mWindowAttributes.surfaceInsets.left, - mWindowAttributes.surfaceInsets.top, - mWidth, mHeight); + if (mUseMTRenderer) { + for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { + updated |= + mWindowCallbacks.get(i).onContentDrawn(mWindowAttributes.surfaceInsets.left, + mWindowAttributes.surfaceInsets.top, mWidth, mHeight); + } } return updated | (mDragResizing && mReportNextDraw); } private void requestDrawWindow() { - if (mReportNextDraw) { - mWindowDrawCountDown = new CountDownLatch(mWindowCallbacks.size()); + if (!mUseMTRenderer) { + return; } + mWindowDrawCountDown = new CountDownLatch(mWindowCallbacks.size()); for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { mWindowCallbacks.get(i).onRequestDraw(mReportNextDraw); } diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java index e14655536c75..72af203e5fab 100644 --- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java +++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java @@ -790,11 +790,14 @@ public final class AccessibilityInteractionClient if (info != null) { info.setConnectionId(connectionId); // Empty array means any package name is Okay - if (!ArrayUtils.isEmpty(packageNames) - && !ArrayUtils.contains(packageNames, info.getPackageName().toString())) { - // If the node package not one of the valid ones, pick the top one - this - // is one of the packages running in the introspected UID. - info.setPackageName(packageNames[0]); + if (!ArrayUtils.isEmpty(packageNames)) { + CharSequence packageName = info.getPackageName(); + if (packageName == null + || !ArrayUtils.contains(packageNames, packageName.toString())) { + // If the node package not one of the valid ones, pick the top one - this + // is one of the packages running in the introspected UID. + info.setPackageName(packageNames[0]); + } } info.setSealed(true); if (!bypassCache) { diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java index f4cbc54b452b..fdc9f92347db 100644 --- a/core/java/android/view/textclassifier/TextClassifier.java +++ b/core/java/android/view/textclassifier/TextClassifier.java @@ -48,8 +48,13 @@ public interface TextClassifier { /** @hide */ @Retention(RetentionPolicy.SOURCE) - @StringDef({ - TYPE_UNKNOWN, TYPE_OTHER, TYPE_EMAIL, TYPE_PHONE, TYPE_ADDRESS, TYPE_URL + @StringDef(prefix = { "TYPE_" }, value = { + TYPE_UNKNOWN, + TYPE_OTHER, + TYPE_EMAIL, + TYPE_PHONE, + TYPE_ADDRESS, + TYPE_URL, }) @interface EntityType {} diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java index 6cf6b69f4aa6..d7aaee73f976 100644 --- a/core/java/android/view/textclassifier/TextClassifierImpl.java +++ b/core/java/android/view/textclassifier/TextClassifierImpl.java @@ -382,7 +382,7 @@ final class TextClassifierImpl implements TextClassifier { } final String type = getHighestScoringType(classifications); - addActions(builder, IntentFactory.create(mContext, type, text)); + addActions(builder, IntentFactory.create(mContext, type, classifiedText)); return builder.setSignature(getSignature(text, start, end)).build(); } diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index df971128b49d..e065dc119880 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -544,7 +544,8 @@ public class Editor { chooseSize(mErrorPopup, mError, tv); tv.setText(mError); - mErrorPopup.showAsDropDown(mTextView, getErrorX(), getErrorY()); + mErrorPopup.showAsDropDown(mTextView, getErrorX(), getErrorY(), + Gravity.TOP | Gravity.LEFT); mErrorPopup.fixDirection(mErrorPopup.isAboveAnchor()); } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index d9bc51fffd6a..f8083babef29 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -77,6 +77,7 @@ import android.text.InputFilter; import android.text.InputType; import android.text.Layout; import android.text.ParcelableSpan; +import android.text.PremeasuredText; import android.text.Selection; import android.text.SpanWatcher; import android.text.Spannable; @@ -5326,7 +5327,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (imm != null) imm.restartInput(this); } else if (type == BufferType.SPANNABLE || mMovement != null) { text = mSpannableFactory.newSpannable(text); - } else if (!(text instanceof CharWrapper)) { + } else if (!(text instanceof PremeasuredText || text instanceof CharWrapper)) { text = TextUtils.stringOrSpannedString(text); } @@ -5610,10 +5611,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener spannable = (Spannable) text; } else { spannable = mSpannableFactory.newSpannable(text); - text = spannable; } SuggestionSpan[] spans = spannable.getSpans(0, text.length(), SuggestionSpan.class); + if (spans.length == 0) { + return text; + } else { + text = spannable; + } + for (int i = 0; i < spans.length; i++) { spannable.removeSpan(spans[i]); } diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java index e5d571672ce2..91c76afdf5b2 100644 --- a/core/java/com/android/internal/util/Preconditions.java +++ b/core/java/com/android/internal/util/Preconditions.java @@ -494,4 +494,38 @@ public class Preconditions { return value; } + + /** + * Ensures that all elements in the argument integer array are within the inclusive range + * + * @param value an integer array of values + * @param lower the lower endpoint of the inclusive range + * @param upper the upper endpoint of the inclusive range + * @param valueName the name of the argument to use if the check fails + * + * @return the validated integer array + * + * @throws IllegalArgumentException if any of the elements in {@code value} were out of range + * @throws NullPointerException if the {@code value} was {@code null} + */ + public static int[] checkArrayElementsInRange(int[] value, int lower, int upper, + String valueName) { + checkNotNull(value, valueName + " must not be null"); + + for (int i = 0; i < value.length; ++i) { + int v = value[i]; + + if (v < lower) { + throw new IllegalArgumentException( + String.format("%s[%d] is out of range of [%d, %d] (too low)", + valueName, i, lower, upper)); + } else if (v > upper) { + throw new IllegalArgumentException( + String.format("%s[%d] is out of range of [%d, %d] (too high)", + valueName, i, lower, upper)); + } + } + + return value; + } } diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index ca8624d9c01e..1fd5564773b1 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -80,7 +80,6 @@ interface IInputMethodManager { boolean switchToLastInputMethod(in IBinder token); boolean switchToNextInputMethod(in IBinder token, boolean onlyCurrentIme); boolean shouldOfferSwitchingToNextInputMethod(in IBinder token); - boolean setInputMethodEnabled(String id, boolean enabled); void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes); int getInputMethodWindowVisibleHeight(); void clearLastInputMethodWindowForTransition(in IBinder token); diff --git a/core/java/com/android/internal/widget/ButtonBarLayout.java b/core/java/com/android/internal/widget/ButtonBarLayout.java index 6a0edef49643..82affe2f86b1 100644 --- a/core/java/com/android/internal/widget/ButtonBarLayout.java +++ b/core/java/com/android/internal/widget/ButtonBarLayout.java @@ -151,7 +151,7 @@ public class ButtonBarLayout extends LinearLayout { private void setStacked(boolean stacked) { setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL); - setGravity(stacked ? Gravity.RIGHT : Gravity.BOTTOM); + setGravity(stacked ? Gravity.END : Gravity.BOTTOM); final View spacer = findViewById(R.id.spacer); if (spacer != null) { diff --git a/core/java/org/chromium/arc/EventLogTags.logtags b/core/java/org/chromium/arc/EventLogTags.logtags new file mode 100644 index 000000000000..1b7160e90224 --- /dev/null +++ b/core/java/org/chromium/arc/EventLogTags.logtags @@ -0,0 +1,11 @@ +# See system/core/logcat/event.logtags for a description of the format of this file. + +option java_package org.chromium.arc + +# We use ID range 300000-399999 for ARC. +# In case of conflicts build will fail, so we do not need to worry too much +# about it. + +# Emitted in ARC system events, such as start of ARC services. +# These events will be watched in automations like autotests. +300000 arc_system_event (event|3) diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp index 460a0d75ca4e..564afeb39490 100644 --- a/core/jni/android/graphics/NinePatch.cpp +++ b/core/jni/android/graphics/NinePatch.cpp @@ -101,7 +101,8 @@ public: SkIRect src = SkIRect::MakeWH(bitmap.width(), bitmap.height()); lattice.fBounds = &src; NinePatchUtils::SetLatticeDivs(&lattice, *chunk, bitmap.width(), bitmap.height()); - lattice.fFlags = nullptr; + lattice.fRectTypes = nullptr; + lattice.fColors = nullptr; SkRegion* region = nullptr; if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), lattice)) { diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp index d3da21b5635b..b9ff0a787931 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -747,7 +747,7 @@ static long long get_zram_mem_used() static void android_os_Debug_getMemInfo(JNIEnv *env, jobject clazz, jlongArray out) { - char buffer[1024]; + char buffer[4096]; size_t numFound = 0; if (out == NULL) { diff --git a/core/proto/android/os/batterystats.proto b/core/proto/android/os/batterystats.proto index cff187992fdb..0fa428e9c114 100644 --- a/core/proto/android/os/batterystats.proto +++ b/core/proto/android/os/batterystats.proto @@ -28,12 +28,8 @@ message BatteryStatsProto { optional int64 parcel_version = 2; optional string start_platform_version = 3; optional string end_platform_version = 4; - optional BatteryHistoryProto history = 5; - repeated UidProto uids = 6; - optional SystemProto system = 7; -} - -message BatteryHistoryProto { + repeated UidProto uids = 5; + optional SystemProto system = 6; } message ControllerActivityProto { diff --git a/core/proto/android/os/system_properties.proto b/core/proto/android/os/system_properties.proto index 921bb5a4b471..7ffdc9628cc6 100644 --- a/core/proto/android/os/system_properties.proto +++ b/core/proto/android/os/system_properties.proto @@ -17,641 +17,483 @@ syntax = "proto2"; option java_multiple_files = true; -option java_outer_classname = "SystemPropertiesProtoMetadata"; +import "frameworks/base/libs/incident/proto/android/privacy.proto"; import "frameworks/base/tools/streaming_proto/stream.proto"; package android.os; -// System Properties from getprop +// Android Platform Exported System Properties +// TODO: This is not the completed list, new properties need to be whitelisted. message SystemPropertiesProto { option (stream_proto.stream_msg).enable_fields_mapping = true; - // Properties that are not specified below are appended here. + // Properties that are not specified below would be appended here. + // These values stay on device only. message Property { + option (android.msg_privacy).dest = DEST_LOCAL; + optional string name = 1; optional string value = 2; } repeated Property extra_properties = 1; - optional int32 aaudio_hw_burst_min_usec = 2; - optional int32 aaudio_mmap_exclusive_policy = 3; - optional int32 aaudio_mmap_policy = 4; - - optional int32 af_fast_track_multiplier = 5; - - optional int32 audio_adm_buffering_ms = 6; - optional int32 audio_hal_period_size = 7; - - optional string dalvik_vm_appimageformat = 8; - optional string dalvik_vm_dex2oat_Xms = 9; - optional string dalvik_vm_dex2oat_Xmx = 10; - optional bool dalvik_vm_dexopt_secondary = 11; - optional string dalvik_vm_heapgrowthlimit = 12; - optional string dalvik_vm_heapmaxfree = 13; - optional string dalvik_vm_heapminfree = 14; - optional string dalvik_vm_heapsize = 15; - optional string dalvik_vm_heapstartsize = 16; - optional float dalvik_vm_heaptargetutilization = 17; - optional string dalvik_vm_image_dex2oat_Xms = 18; - optional string dalvik_vm_image_dex2oat_Xmx = 19; - optional string dalvik_vm_image_dex2oat_filter = 20; - optional string dalvik_vm_isa_arm_features = 21; - optional string dalvik_vm_isa_arm_variant = 22; - optional string dalvik_vm_isa_arm64_features = 23; - optional string dalvik_vm_isa_arm64_variant = 24; - optional int32 dalvik_vm_lockprof_threshold = 25; - optional string dalvik_vm_stack_trace_dir = 26; - optional bool dalvik_vm_usejit = 27; - optional bool dalvik_vm_usejitprofiles = 28; - - optional int32 debug_atrace_tags_enableflags = 29; - optional int32 debug_force_rtl = 30; - optional string debug_htc_hrdump = 31; - - optional int32 dev_bootcomplete = 32; - - optional bool drm_service_enabled = 33; - - optional int32 fmas_hdph_sgain = 34; - - optional int32 gsm_current_phone_type = 35; - optional string gsm_network_type = 36; - optional string gsm_operator_alpha = 37; - optional string gsm_operator_iso_country = 38; - optional bool gsm_operator_isroaming = 39; - optional string gsm_operator_numeric = 40; - optional string gsm_sim_operator_alpha = 41; - optional string gsm_sim_operator_iso_country = 42; - optional int32 gsm_sim_operator_numeric = 43; - optional string gsm_sim_state = 44; - optional string gsm_version_baseband = 45; - optional string gsm_version_ril_impl = 46; - - optional sint32 htc_camera_sensor_inf = 47; - - optional bool hwservicemanager_ready = 48; - - // Enum values for a lot of system properties - enum Status { - STATUS_UNKNOWN = 0; - STATUS_RUNNING = 1; - STATUS_STOPPED = 2; + optional int32 aac_drc_boost = 2; + optional int32 aac_drc_cut = 3; + optional int32 aac_drc_enc_target_level = 4; + optional int32 aac_drc_heavy = 5; + optional int32 aac_drc_reference_level = 6; + + message Aaudio { + option (stream_proto.stream_msg).enable_fields_mapping = true; + + optional int32 hw_burst_min_usec = 1; + optional int32 minimum_sleep_usec = 2; + optional int32 mixer_bursts = 3; + optional int32 mmap_exclusive_policy = 4; + optional int32 mmap_policy = 5; + optional int32 wakeup_delay_usec = 6; + + // Next Tag: 7 + } + optional Aaudio aaudio = 7; + + optional int32 af_fast_track_multiplier = 8; + + message Camera { + option (stream_proto.stream_msg).enable_fields_mapping = true; + + optional bool disable_zsl_mode = 1; + optional int32 fifo_disable = 2; + + // Next Tag: 3 + } + optional Camera camera = 9; + + message DalvikVm { + option (stream_proto.stream_msg).enable_fields_mapping = true; + + optional string appimageformat = 1; + optional string backgroundgctype = 2; + optional bool checkjni = 3; + optional string dex2oat_filter = 4; + optional string dex2oat_flags = 5; + optional int32 dex2oat_threads = 6; + optional string dex2oat_Xms = 7; + optional string dex2oat_Xmx = 8; + optional bool dexopt_secondary = 9; + optional string execution_mode = 10; + optional string extra_opts = 11; + optional string gctype = 12; + optional string heapgrowthlimit = 13; + optional string heapmaxfree = 14; + optional string heapminfree = 15; + optional string heapsize = 16; + optional string heapstartsize = 17; + optional double heaptargetutilization = 18; + optional int32 hot_startup_method_samples = 19; + optional string image_dex2oat_filter = 20; + optional string image_dex2oat_flags = 21; + optional int32 image_dex2oat_threads = 22; + optional string image_dex2oat_Xms = 23; + optional string image_dex2oat_Xmx = 24; + optional string isa_arm_features = 25; + optional string isa_arm_variant = 26; + optional string isa_arm64_features = 27; + optional string isa_arm64_variant = 28; + optional string isa_mips_features = 29; + optional string isa_mips_variant = 30; + optional string isa_mips64_features = 31; + optional string isa_mips64_variant = 32; + optional string isa_unknown_features = 33; + optional string isa_unknown_variant = 34; + optional string isa_x86_64_features = 35; + optional string isa_x86_64_variant = 36; + optional string isa_x86_features = 37; + optional string isa_x86_variant = 38; + optional string jitinitialsize = 39; + optional string jitmaxsize = 40; + optional int32 jitprithreadweight = 41; + optional int32 jitthreshold = 42; + optional int32 jittransitionweight = 43; + optional string jniopts = 44; + optional int32 lockprof_threshold = 45; + optional bool method_trace = 46; + optional string method_trace_file = 47; + optional int32 method_trace_file_siz = 48; + optional bool method_trace_stream = 49; + optional bool profilesystemserver = 50; + optional string stack_trace_dir = 51; + optional bool usejit = 52; + optional bool usejitprofiles = 53; + optional int32 zygote_max_boot_retry = 54; + + // Next Tag: 55 + } + optional DalvikVm dalvik_vm = 10; + + optional bool drm_64bit_enabled = 11; + optional bool drm_service_enabled = 12; + optional bool dumpstate_dry_run = 13; + optional string gsm_sim_operator_numeric = 14; + optional bool hal_instrumentation_enable = 15; + + message InitSvc { + option (stream_proto.stream_msg).enable_fields_mapping = true; + + enum Status { + STATUS_UNKNOWN = 0; + STATUS_RUNNING = 1; + STATUS_STOPPED = 2; + } + optional Status adbd = 1; + optional Status audioserver = 2; + optional Status bootanim = 3; + optional Status bufferhubd = 4; + optional Status cameraserver = 5; + optional Status clear_bcb = 6; + optional Status drm = 7; + optional Status gatekeeperd = 8; + optional Status healthd = 9; + optional Status hidl_memory = 10; + optional Status hostapd = 11; + optional Status hwservicemanager = 12; + optional Status installd = 13; + optional Status keystore = 14; + optional Status lmkd = 15; + optional Status logd = 16; + optional Status logd_reinit = 17; + optional Status media = 18; + optional Status mediadrm = 19; + optional Status mediaextractor = 20; + optional Status mediametrics = 21; + optional Status netd = 22; + optional Status performanced = 23; + optional Status ril_daemon = 24; + optional Status servicemanager = 25; + optional Status storaged = 26; + optional Status surfaceflinger = 27; + optional Status thermalservice = 28; + optional Status tombstoned = 29; + optional Status ueventd = 30; + optional Status update_engine = 31; + optional Status update_verifier_nonencrypted = 32; + optional Status virtual_touchpad = 33; + optional Status vndservicemanager = 34; + optional Status vold = 35; + optional Status vr_hwc = 36; + optional Status webview_zygote32 = 37; + optional Status wificond = 38; + optional Status wpa_supplicant = 39; + optional Status zygote = 40; + optional Status zygote_secondary = 41; + + // Next Tag: 42 + } + optional InitSvc init_svc = 16; + + optional bool keyguard_no_require_sim = 17; + optional string libc_debug_malloc_options = 18; + optional string libc_debug_malloc_program = 19; + + message Log { + option (stream_proto.stream_msg).enable_fields_mapping = true; + + optional string tag_WifiHAL = 1; + optional string tag_stats_log = 2; + + // Next Tag: 3 } - optional Status init_svc_adbd = 49; - optional Status init_svc_audioserver = 50; - optional Status init_svc_bootanim = 51; - optional Status init_svc_bufferhubd = 52; - optional Status init_svc_cameraserver = 53; - optional Status init_svc_clear_bcb = 54; - optional Status init_svc_drm = 55; - optional Status init_svc_gatekeeperd = 56; - optional Status init_svc_healthd = 57; - optional Status init_svc_hidl_memory = 58; - optional Status init_svc_hostapd = 59; - optional Status init_svc_hwservicemanager = 60; - optional Status init_svc_installd = 61; - optional Status init_svc_keystore = 62; - optional Status init_svc_lmkd = 63; - optional Status init_svc_logd = 64; - optional Status init_svc_logd_reinit = 65; - optional Status init_svc_media = 66; - optional Status init_svc_mediadrm = 67; - optional Status init_svc_mediaextractor = 68; - optional Status init_svc_mediametrics = 69; - optional Status init_svc_netd = 70; - optional Status init_svc_performanced = 71; - optional Status init_svc_ril_daemon = 72; - optional Status init_svc_servicemanager = 73; - optional Status init_svc_storaged = 74; - optional Status init_svc_surfaceflinger = 75; - optional Status init_svc_thermalservice = 76; - optional Status init_svc_tombstoned = 77; - optional Status init_svc_ueventd = 78; - optional Status init_svc_update_engine = 79; - optional Status init_svc_update_verifier_nonencrypted = 80; - optional Status init_svc_vendor_adsprpcd = 81; - optional Status init_svc_vendor_atfwd = 82; - optional Status init_svc_vendor_audio_hal_2_0 = 83; - optional Status init_svc_vendor_bluetooth_1_0 = 84; - optional Status init_svc_vendor_boot_hal_1_0 = 85; - optional Status init_svc_vendor_camera_provider_2_4 = 86; - optional Status init_svc_vendor_cas_hal_1_0 = 87; - optional Status init_svc_vendor_cnd = 88; - optional Status init_svc_vendor_cnss_daemon = 89; - optional Status init_svc_vendor_cnss_diag = 90; - optional Status init_svc_vendor_configstore_hal = 91; - optional Status init_svc_vendor_contexthub_hal_1_0 = 92; - optional Status init_svc_vendor_devstart_sh = 93; - optional Status init_svc_vendor_drm_hal_1_0 = 94; - optional Status init_svc_vendor_drm_widevine_hal_1_0 = 95; - optional Status init_svc_vendor_dumpstate_1_0 = 96; - optional Status init_svc_vendor_flash_nanohub_fw = 97; - optional Status init_svc_vendor_foreground_sh = 98; - optional Status init_svc_vendor_fps_hal = 99; - optional Status init_svc_vendor_gatekeeper_1_0 = 100; - optional Status init_svc_vendor_gnss_service = 101; - optional Status init_svc_vendor_gralloc_2_0 = 102; - optional Status init_svc_vendor_hci_filter_root = 103; - optional Status init_svc_vendor_hwcomposer_2_1 = 104; - optional Status init_svc_vendor_imsdatadaemon = 105; - optional Status init_svc_vendor_imsqmidaemon = 106; - optional Status init_svc_vendor_init_radio_sh = 107; - optional Status init_svc_vendor_irsc_util = 108; - optional Status init_svc_vendor_keymaster_3_0 = 109; - optional Status init_svc_vendor_light_hal_2_0 = 110; - optional Status init_svc_vendor_loc_launcher = 111; - optional Status init_svc_vendor_media_omx = 112; - optional Status init_svc_vendor_memtrack_hal_1_0 = 113; - optional Status init_svc_vendor_mid_sh = 114; - optional Status init_svc_vendor_msm_irqbalance = 115; - optional Status init_svc_vendor_nanohub_slpi = 116; - optional Status init_svc_vendor_netmgrd = 117; - optional Status init_svc_vendor_nfc_hal_service = 118; - optional Status init_svc_vendor_per_mgr = 119; - optional Status init_svc_vendor_per_proxy = 120; - optional Status init_svc_vendor_perfd = 121; - optional Status init_svc_vendor_port_bridge = 122; - optional Status init_svc_vendor_power_hal_1_1 = 123; - optional Status init_svc_vendor_power_sh = 124; - optional Status init_svc_vendor_qseecomd = 125; - optional Status init_svc_vendor_ramdump_auto = 126; - optional Status init_svc_vendor_rmt_storage = 127; - optional Status init_svc_vendor_sensors_hal_1_0 = 128; - optional Status init_svc_vendor_ss_ramdump = 129; - optional Status init_svc_vendor_ssr_setup = 130; - optional Status init_svc_vendor_thermal_engine = 131; - optional Status init_svc_vendor_time_daemon = 132; - optional Status init_svc_vendor_usb_hal_1_1 = 133; - optional Status init_svc_vendor_vibrator_1_0 = 134; - optional Status init_svc_vendor_vr_1_0 = 135; - optional Status init_svc_vendor_wifi_hal_legacy = 136; - optional Status init_svc_virtual_touchpad = 137; - optional Status init_svc_vndservicemanager = 138; - optional Status init_svc_vold = 139; - optional Status init_svc_vr_hwc = 140; - optional Status init_svc_webview_zygote32 = 141; - optional Status init_svc_wificond = 142; - optional Status init_svc_wpa_supplicant = 143; - optional Status init_svc_zygote = 144; - optional Status init_svc_zygote_secondary = 145; - - optional bool keyguard_no_require_sim = 146; - - optional string log_tag_WifiHAL = 147; - - optional bool logd_logpersistd_enable = 148; - - optional bool media_mediadrmservice_enable = 149; - optional bool media_recorder_show_manufacturer_and_model = 150; - - optional string net_bt_name = 151; - optional string net_dns1 = 152; - optional string net_dns2 = 153; - optional string net_dns3 = 154; - optional string net_dns4 = 155; - optional bool net_lte_ims_data_enabled = 156; - optional int32 net_qtaguid_enabled = 157; - optional int32 net_tcp_2g_init_rwnd = 158; - repeated int32 net_tcp_buffersize_default = 159; - repeated int32 net_tcp_buffersize_edge = 160; - repeated int32 net_tcp_buffersize_evdo = 161; - repeated int32 net_tcp_buffersize_gprs = 162; - repeated int32 net_tcp_buffersize_hsdpa = 163; - repeated int32 net_tcp_buffersize_hspa = 164; - repeated int32 net_tcp_buffersize_hspap = 165; - repeated int32 net_tcp_buffersize_hsupa = 166; - repeated int32 net_tcp_buffersize_lte = 167; - repeated int32 net_tcp_buffersize_umts = 168; - repeated int32 net_tcp_buffersize_wifi = 169; - optional int32 net_tcp_default_init_rwnd = 170; - - optional bool nfc_initialized = 171; - - optional bool persist_audio_fluence_speaker = 172; - optional bool persist_audio_fluence_voicecall = 173; - optional bool persist_audio_fluence_voicecomm = 174; - optional bool persist_audio_fluence_voicerec = 175; - - optional int32 persist_camera_debug_logfile = 176; - optional int32 persist_camera_eis_enable = 177; - optional int32 persist_camera_gyro_android = 178; - optional int32 persist_camera_is_type = 179; - optional int32 persist_camera_tnr_preview = 180; - optional int32 persist_camera_tnr_video = 181; - optional int32 persist_camera_tof_direct = 182; - - optional int32 persist_cne_feature = 183; - - optional bool persist_data_iwlan_enable = 184; - optional string persist_data_mode = 185; - - optional int32 persist_radio_RATE_ADAPT_ENABLE = 186; - optional int32 persist_radio_ROTATION_ENABLE = 187; - optional int32 persist_radio_VT_ENABLE = 188; - optional int32 persist_radio_VT_HYBRID_ENABLE = 189; - optional int32 persist_radio_adb_log_on = 190; - optional int32 persist_radio_airplane_mode_on = 191; - optional int32 persist_radio_apm_sim_not_pwdn = 192; - optional int32 persist_radio_custom_ecc = 193; - optional bool persist_radio_data_con_rprt = 194; - optional int32 persist_radio_data_ltd_sys_ind = 195; - optional string persist_radio_enable_tel_mon = 196; - optional bool persist_radio_eons_enabled = 197; - optional bool persist_radio_is_wps_enabled = 198; - optional int32 persist_radio_pwropt_modepref_0 = 199; - optional int32 persist_radio_ril_payload_on = 200; - optional int32 persist_radio_sglte_target = 201; - optional int32 persist_radio_sib16_support = 202; - optional int32 persist_radio_smlog_switch = 203; - optional int32 persist_radio_snapshot_enabled = 204; - optional int32 persist_radio_snapshot_timer = 205; - optional int32 persist_radio_sw_mbn_loaded = 206; - optional int32 persist_radio_sw_mbn_update = 207; - optional string persist_radio_ver_info = 208; - optional int32 persist_radio_videopause_mode = 209; - - optional int32 persist_rcs_supported = 210; - - optional string persist_sys_boot_reason = 211; - optional int32 persist_sys_cnd_iwlan = 212; - optional string persist_sys_dalvik_vm_lib_2 = 213; - optional string persist_sys_gps_lpp = 214; - optional string persist_sys_locale = 215; - optional int32 persist_sys_ssr_enable_ramdumps = 216; - optional string persist_sys_ssr_restart_level = 217; - optional string persist_sys_timezone = 218; - optional string persist_sys_usb_config = 219; - optional int32 persist_sys_webview_vmsize = 220; - - optional string pm_dexopt_ab_ota = 221; - optional string pm_dexopt_bg_dexopt = 222; - optional string pm_dexopt_boot = 223; - optional string pm_dexopt_first_boot = 224; - optional string pm_dexopt_inactive = 225; - optional string pm_dexopt_install = 226; - optional string pm_dexopt_shared = 227; - - optional string qcom_bluetooth_soc = 228; - - optional int32 qdcm_diagonal_matrix_mode = 229; - optional int32 qdcm_only_pcc_for_trans = 230; - - repeated string ril_ecclist = 231; - optional int32 ril_power_backoff_suppressed = 232; - optional int32 ril_qcril_pre_init_lock_held = 233; - optional string ril_voice_network_type = 234; - optional string rild_libpath = 235; - - optional int32 ro_adb_secure = 236; - optional int32 ro_allow_mock_location = 237; - repeated string ro_atrace_core_services = 238; - optional string ro_baseband = 239; - optional int32 ro_bionic_ld_warning = 240; - optional bool ro_bluetooth_dun = 241; - optional string ro_bluetooth_hfp_ver = 242; - optional bool ro_bluetooth_sap = 243; - optional string ro_board_platform = 244; - - optional string ro_boot_baseband = 245; - optional string ro_boot_bootdevice = 246; - optional string ro_boot_bootloader = 247; - optional string ro_boot_bootreason = 248; - repeated string ro_boot_boottime = 249; - optional int32 ro_boot_cid = 250; - optional string ro_boot_console = 251; - optional string ro_boot_ddrinfo = 252; - optional string ro_boot_ddrsize = 253; - optional int32 ro_boot_flash_locked = 254; - optional int32 ro_boot_fp_src = 255; - optional string ro_boot_hardware = 256; - optional string ro_boot_hardware_color = 257; - optional string ro_boot_hardware_ddr = 258; - optional string ro_boot_hardware_revision = 259; - optional string ro_boot_hardware_sku = 260; - optional string ro_boot_hardware_ufs = 261; - optional string ro_boot_htc_hrdump = 262; - optional int32 ro_boot_keymaster = 263; - optional string ro_boot_mid = 264; - optional int32 ro_boot_msm_hw_ver_id = 265; - optional int32 ro_boot_oem_unlock_support = 266; - optional int32 ro_boot_qf_st = 267; - optional int32 ro_boot_ramdump_enable = 268; - optional string ro_boot_serialno = 269; - optional string ro_boot_slot_suffix = 270; - optional int32 ro_boot_temp_protect_ignore = 271; - optional string ro_boot_vendor_overlay_theme = 272; - optional string ro_boot_verifiedbootstate = 273; - optional string ro_boot_veritymode = 274; - optional string ro_boot_wificountrycode = 275; - - optional string ro_bootimage_build_date = 276; - optional int64 ro_bootimage_build_date_utc = 277; - optional string ro_bootimage_build_fingerprint = 278; - - optional string ro_bootloader = 279; - optional string ro_bootmode = 280; - - optional int64 ro_boottime_adbd = 281; - optional int64 ro_boottime_audioserver = 282; - optional int64 ro_boottime_bootanim = 283; - optional int64 ro_boottime_bufferhubd = 284; - optional int64 ro_boottime_cameraserver = 285; - optional int64 ro_boottime_clear_bcb = 286; - optional int64 ro_boottime_drm = 287; - optional int64 ro_boottime_gatekeeperd = 288; - optional int64 ro_boottime_healthd = 289; - optional int64 ro_boottime_hidl_memory = 290; - optional int64 ro_boottime_hwservicemanager = 291; - optional int64 ro_boottime_init = 292; - optional int64 ro_boottime_init_cold_boot_wait = 293; - optional int32 ro_boottime_init_mount_all_early = 294; - optional int32 ro_boottime_init_mount_all_late = 295; - optional int32 ro_boottime_init_selinux = 296; - optional int64 ro_boottime_installd = 297; - optional int64 ro_boottime_keystore = 298; - optional int64 ro_boottime_lmkd = 299; - optional int64 ro_boottime_logd = 300; - optional int64 ro_boottime_logd_reinit = 301; - optional int64 ro_boottime_media = 302; - optional int64 ro_boottime_mediadrm = 303; - optional int64 ro_boottime_mediaextractor = 304; - optional int64 ro_boottime_mediametrics = 305; - optional int64 ro_boottime_netd = 306; - optional int64 ro_boottime_performanced = 307; - optional int64 ro_boottime_ril_daemon = 308; - optional int64 ro_boottime_servicemanager = 309; - optional int64 ro_boottime_storaged = 310; - optional int64 ro_boottime_surfaceflinger = 311; - optional int64 ro_boottime_thermalservice = 312; - optional int64 ro_boottime_tombstoned = 313; - optional int64 ro_boottime_ueventd = 314; - optional int64 ro_boottime_update_engine = 315; - optional int64 ro_boottime_update_verifier_nonencrypted = 316; - optional int64 ro_boottime_vendor_adsprpcd = 317; - optional int64 ro_boottime_vendor_atfwd = 318; - optional int64 ro_boottime_vendor_audio_hal_2_0 = 319; - optional int64 ro_boottime_vendor_bluetooth_1_0 = 320; - optional int64 ro_boottime_vendor_boot_hal_1_0 = 321; - optional int64 ro_boottime_vendor_camera_provider_2_4 = 322; - optional int64 ro_boottime_vendor_cas_hal_1_0 = 323; - optional int64 ro_boottime_vendor_cnd = 324; - optional int64 ro_boottime_vendor_cnss_daemon = 325; - optional int64 ro_boottime_vendor_cnss_diag = 326; - optional int64 ro_boottime_vendor_configstore_hal = 327; - optional int64 ro_boottime_vendor_contexthub_hal_1_0 = 328; - optional int64 ro_boottime_vendor_devstart_sh = 329; - optional int64 ro_boottime_vendor_drm_hal_1_0 = 330; - optional int64 ro_boottime_vendor_drm_widevine_hal_1_0 = 331; - optional int64 ro_boottime_vendor_dumpstate_1_0 = 332; - optional int64 ro_boottime_vendor_flash_nanohub_fw = 333; - optional int64 ro_boottime_vendor_foreground_sh = 334; - optional int64 ro_boottime_vendor_fps_hal = 335; - optional int64 ro_boottime_vendor_gatekeeper_1_0 = 336; - optional int64 ro_boottime_vendor_gnss_service = 337; - optional int64 ro_boottime_vendor_gralloc_2_0 = 338; - optional int64 ro_boottime_vendor_hci_filter_root = 339; - optional int64 ro_boottime_vendor_hwcomposer_2_1 = 340; - optional int64 ro_boottime_vendor_imsdatadaemon = 341; - optional int64 ro_boottime_vendor_imsqmidaemon = 342; - optional int64 ro_boottime_vendor_init_radio_sh = 343; - optional int64 ro_boottime_vendor_irsc_util = 344; - optional int64 ro_boottime_vendor_keymaster_3_0 = 345; - optional int64 ro_boottime_vendor_light_hal_2_0 = 346; - optional int64 ro_boottime_vendor_loc_launcher = 347; - optional int64 ro_boottime_vendor_media_omx = 348; - optional int64 ro_boottime_vendor_memtrack_hal_1_0 = 349; - optional int64 ro_boottime_vendor_mid_sh = 350; - optional int64 ro_boottime_vendor_msm_irqbalance = 351; - optional int64 ro_boottime_vendor_nanohub_slpi = 352; - optional int64 ro_boottime_vendor_netmgrd = 353; - optional int64 ro_boottime_vendor_nfc_hal_service = 354; - optional int64 ro_boottime_vendor_per_mgr = 355; - optional int64 ro_boottime_vendor_per_proxy = 356; - optional int64 ro_boottime_vendor_perfd = 357; - optional int64 ro_boottime_vendor_port_bridge = 358; - optional int64 ro_boottime_vendor_power_hal_1_1 = 359; - optional int64 ro_boottime_vendor_power_sh = 360; - optional int64 ro_boottime_vendor_qseecomd = 361; - optional int64 ro_boottime_vendor_ramdump_auto = 362; - optional int64 ro_boottime_vendor_rmt_storage = 363; - optional int64 ro_boottime_vendor_sensors_hal_1_0 = 364; - optional int64 ro_boottime_vendor_ss_ramdump = 365; - optional int64 ro_boottime_vendor_ssr_setup = 366; - optional int64 ro_boottime_vendor_thermal_engine = 367; - optional int64 ro_boottime_vendor_time_daemon = 368; - optional int64 ro_boottime_vendor_usb_hal_1_1 = 369; - optional int64 ro_boottime_vendor_vibrator_1_0 = 370; - optional int64 ro_boottime_vendor_vr_1_0 = 371; - optional int64 ro_boottime_vendor_wifi_hal_legacy = 372; - optional int64 ro_boottime_virtual_touchpad = 373; - optional int64 ro_boottime_vndservicemanager = 374; - optional int64 ro_boottime_vold = 375; - optional int64 ro_boottime_vr_hwc = 376; - optional int64 ro_boottime_webview_zygote32 = 377; - optional int64 ro_boottime_wificond = 378; - optional int64 ro_boottime_wpa_supplicant = 379; - optional int64 ro_boottime_zygote = 380; - optional int64 ro_boottime_zygote_secondary = 381; - - optional string ro_bt_bdaddr_path = 382; - - optional bool ro_build_ab_update = 383; - optional string ro_build_characteristics = 384; - optional string ro_build_date = 385; - optional int64 ro_build_date_utc = 386; - optional string ro_build_description = 387; - optional string ro_build_display_id = 388; - optional string ro_build_expect_baseband = 389; - optional string ro_build_expect_bootloader = 390; - optional string ro_build_fingerprint = 391; - optional string ro_build_flavor = 392; - optional string ro_build_host = 393; - optional string ro_build_id = 394; - optional string ro_build_product = 395; - optional bool ro_build_system_root_image = 396; - optional string ro_build_tags = 397; - optional string ro_build_type = 398; - optional string ro_build_user = 399; - optional string ro_build_version_all_codenames = 400; - optional string ro_build_version_base_os = 401; - optional string ro_build_version_codename = 402; - optional string ro_build_version_incremental = 403; - optional int32 ro_build_version_preview_sdk = 404; - optional string ro_build_version_release = 405; - optional int32 ro_build_version_sdk = 406; - optional string ro_build_version_security_patch = 407; - - optional int32 ro_camera_notify_nfc = 408; - optional string ro_carrier = 409; - optional bool ro_com_android_dataroaming = 410; - optional bool ro_com_android_prov_mobiledata = 411; - optional string ro_com_google_clientidbase = 412; - optional int32 ro_com_google_ime_theme_id = 413; - - optional string ro_config_alarm_alert = 414; - optional string ro_config_notification_sound = 415; - optional string ro_config_ringtone = 416; - optional int32 ro_config_vc_call_vol_steps = 417; - optional string ro_control_privapp_permissions = 418; - optional int32 ro_cp_system_other_odex = 419; - - optional string ro_crypto_scrypt_params = 420; - optional string ro_crypto_state = 421; - optional string ro_crypto_type = 422; - optional string ro_crypto_volume_filenames_mode = 423; - optional int32 ro_dalvik_vm_native_bridge = 424; - optional int32 ro_debuggable = 425; - optional bool ro_device_owner = 426; - optional string ro_error_receiver_system_apps = 427; - - optional int32 ro_facelock_black_timeout = 428; - optional int32 ro_facelock_det_timeout = 429; - optional int32 ro_facelock_est_max_time = 430; - optional int32 ro_facelock_rec_timeout = 431; - - optional string ro_frp_pst = 432; - - optional string ro_hardware = 433; - optional string ro_hardware_power = 434; - - optional int32 ro_hwui_drop_shadow_cache_size = 435; - optional int32 ro_hwui_gradient_cache_size = 436; - optional int32 ro_hwui_layer_cache_size = 437; - optional int32 ro_hwui_path_cache_size = 438; - optional int32 ro_hwui_r_buffer_cache_size = 439; - optional int32 ro_hwui_text_large_cache_height = 440; - optional int32 ro_hwui_text_large_cache_width = 441; - optional int32 ro_hwui_text_small_cache_height = 442; - optional int32 ro_hwui_text_small_cache_width = 443; - optional float ro_hwui_texture_cache_flushrate = 444; - optional int32 ro_hwui_texture_cache_size = 445; - - optional bool ro_init_subcontexts_enabled = 446; - optional int32 ro_kernel_android_checkjni = 447; - optional string ro_logd_size = 448; - optional int32 ro_min_freq_0 = 449; - optional int32 ro_oem_unlock_supported = 450; - optional bool ro_opa_eligible_device = 451; - optional int32 ro_opengles_version = 452; - optional bool ro_persistent_properties_ready = 453; - - optional string ro_product_board = 454; - optional string ro_product_brand = 455; - optional string ro_product_cpu_abi = 456; - repeated string ro_product_cpu_abilist = 457; - repeated string ro_product_cpu_abilist32 = 458; - optional string ro_product_cpu_abilist64 = 459; - optional string ro_product_device = 460; - optional int32 ro_product_first_api_level = 461; - optional string ro_product_locale = 462; - optional string ro_product_manufacturer = 463; - optional string ro_product_model = 464; - optional string ro_product_name = 465; - optional string ro_product_vendor_brand = 466; - optional string ro_product_vendor_device = 467; - optional string ro_product_vendor_manufacturer = 468; - optional string ro_product_vendor_model = 469; - optional string ro_product_vendor_name = 470; - - optional int32 ro_property_service_version = 471; - optional string ro_qc_sdk_audio_fluencetype = 472; - optional int32 ro_qcom_adreno_qgl_ShaderStorageImageExtendedFormats = 473; - optional bool ro_qualcomm_bluetooth_ftp = 474; - optional bool ro_qualcomm_bluetooth_hfp = 475; - optional bool ro_qualcomm_bluetooth_hsp = 476; - optional bool ro_qualcomm_bluetooth_map = 477; - optional bool ro_qualcomm_bluetooth_nap = 478; - optional bool ro_qualcomm_bluetooth_opp = 479; - optional bool ro_qualcomm_bluetooth_pbap = 480; - - optional string ro_radio_log_loc = 481; - optional string ro_radio_log_prefix = 482; - optional int32 ro_revision = 483; - optional bool ro_ril_svdo = 484; - optional bool ro_ril_svlte1x = 485; - optional int64 ro_runtime_firstboot = 486; - optional int32 ro_secure = 487; - optional string ro_serialno = 488; - optional int32 ro_setupwizard_enterprise_mode = 489; - optional bool ro_setupwizard_rotation_locked = 490; - optional int32 ro_sf_lcd_density = 491; - optional bool ro_storage_manager_enabled = 492; - optional bool ro_telephony_call_ring_multiple = 493; - optional int32 ro_telephony_default_cdma_sub = 494; - optional int32 ro_telephony_default_network = 495; - optional bool ro_treble_enabled = 496; - optional string ro_url_legal = 497; - optional string ro_url_legal_android_privacy = 498; - optional string ro_vendor_build_date = 499; - optional int64 ro_vendor_build_date_utc = 500; - optional string ro_vendor_build_fingerprint = 501; - optional string ro_vendor_extension_library = 502; - optional bool ro_wallpapers_loc_request_suw = 503; - optional string ro_wifi_channels = 504; - optional string ro_zygote = 505; - - optional int32 sdm_debug_disable_rotator_split = 506; - - optional string selinux_restorecon_recursive = 507; - - optional string sendbug_preferred_domain = 508; - - optional string sensors_contexthub_lid_state = 509; - - optional int32 service_bootanim_exit = 510; - optional int32 service_sf_present_timestamp = 511; - - optional string setupwizard_theme = 512; - - optional string sys_boot_reason = 513; - optional int32 sys_boot_completed = 514; - optional int32 sys_ims_QMI_DAEMON_STATUS = 515; - optional bool sys_keymaster_loaded = 516; - optional bool sys_listeners_registered = 517; - optional int32 sys_logbootcomplete = 518; - optional int32 sys_oem_unlock_allowed = 519; - optional int32 sys_post_boot_parsed = 520; - optional int32 sys_qcom_devup = 521; - optional int32 sys_retaildemo_enabled = 522; - optional string sys_slpi_firmware_version = 523; - optional int32 sys_sysctl_extra_free_kbytes = 524; - optional int32 sys_sysctl_tcp_def_init_rwnd = 525; - optional bool sys_time_set = 526; - optional string sys_usb_config = 527; - optional int32 sys_usb_configfs = 528; - optional string sys_usb_controller = 529; - optional int32 sys_usb_ffs_max_read = 530; - optional int32 sys_usb_ffs_max_write = 531; - optional int32 sys_usb_ffs_mtp_ready = 532; - optional int32 sys_usb_ffs_ready = 533; - optional int32 sys_usb_mtp_device_type = 534; - optional int32 sys_usb_rps_mask = 535; - optional string sys_usb_state = 536; - optional bool sys_user_0_ce_available = 537; - optional int32 sys_wifitracing_started = 538; - - optional int32 telephony_lteOnCdmaDevice = 539; - - optional int32 tombstoned_max_tombstone_count = 540; - - optional int32 vidc_debug_perf_mode = 541; - - optional int32 vold_has_adoptable = 542; - optional int32 vold_has_quota = 543; - optional int32 vold_post_fs_data_done = 544; - - optional int32 wc_transport_clean_up = 545; - optional int32 wc_transport_hci_filter_status = 546; - optional string wc_transport_patch_dnld_inprog = 547; - optional int32 wc_transport_ref_count = 548; - optional int32 wc_transport_soc_initialized = 549; - optional bool wc_transport_start_root = 550; - optional int32 wc_transport_vnd_power = 551; - - optional string wifi_interface = 552; - optional string wlan_driver_status = 553; - - // Next Tag: 554 + optional Log log = 20; + + optional bool media_mediadrmservice_enable = 21; + optional bool media_recorder_show_manufacturer_and_model = 22; + + message Persist { + option (stream_proto.stream_msg).enable_fields_mapping = true; + + optional string config_calibration_fac = 1; + optional int32 dbg_volte_avail_ovr = 2; + optional int32 dbg_vt_avail_ovr = 3; + optional int32 dbg_wfc_avail_ovr = 4; + optional int32 radio_airplane_mode_on = 5; + optional string radio_multisim_config = 6; + optional int32 rcs_supported = 7; + optional bool sys_crash_rcu = 8; + optional string sys_dalvik_vm_lib_2 = 9; + optional float sys_sf_color_saturation = 10; + optional string sys_timezone = 11; + + // Next Tag: 12 + } + optional Persist persist = 23; + + message PmDexopt { + option (stream_proto.stream_msg).enable_fields_mapping = true; + + optional string ab_ota = 1; + optional string bg_dexopt = 2; + optional string boot = 3; + optional string first_boot = 4; + optional string install = 5; + + // Next Tag: 6 + } + optional PmDexopt pm_dexopt = 24; + + message Ro { + option (stream_proto.stream_msg).enable_fields_mapping = true; + + optional int32 adb_secure = 1; + optional string arch = 2; + optional bool audio_ignore_effects = 3; + optional bool audio_monitorRotation = 4; + optional string baseband = 5; + optional string board_platform = 6; + + message Boot { + option (stream_proto.stream_msg).enable_fields_mapping = true; + + optional string avb_version = 1; + optional string baseband = 2; + optional string bootdevice = 3; + optional string bootloader = 4; + repeated string boottime = 5; + optional string console = 6; + optional int32 fake_battery = 7; + optional string hardware = 8; + optional string hardware_color = 9; + optional string hardware_revision = 10; + optional string hardware_sku = 11; + optional string keymaster = 12; + optional string mode = 13; + optional string revision = 14; + optional string slot_suffix = 15; + optional string vbmeta_avb_version = 16; + optional string vendor_overlay_theme = 17; + optional string verifiedbootstate = 18; + optional string veritymode = 19; + optional string wificountrycode = 20; + + // Next Tag: 21 + } + optional Boot boot = 7; + + message BootImage { + option (stream_proto.stream_msg).enable_fields_mapping = true; + + optional string build_date = 1; + optional int32 build_date_utc = 2; + optional string build_fingerprint = 3; + + // Next Tag: 4 + } + optional BootImage bootimage = 8; + + optional string bootloader = 9; + optional string bootmode = 10; + + message Build { + option (stream_proto.stream_msg).enable_fields_mapping = true; + + optional string date = 1; + optional int32 date_utc = 2; + optional string description = 3; + optional string display_id = 4; + optional string host = 5; + optional string id = 6; + optional string product = 7; + optional bool system_root_image = 8; + optional string tags = 9; + optional string type = 10; + optional string user = 11; + + message Version { + option (stream_proto.stream_msg).enable_fields_mapping = true; + + optional string version_base_os = 1; + optional string version_codename = 2; + optional string version_incremental = 3; + optional int32 version_preview_sdk = 4; + optional string version_release = 5; + optional int32 version_sdk = 6; + optional string version_security_patch = 7; + + // Next Tag: 8 + } + optional Version version = 12; + + // Next Tag: 13 + } + optional Build build = 11; + + optional int32 camera_notify_nfc = 12; + optional string carrier = 13; + optional bool com_android_dataroaming = 14; + optional bool com_android_prov_mobiledata = 15; + optional string com_google_clientidbase = 16; + + message Config { + option (stream_proto.stream_msg).enable_fields_mapping = true; + + optional string alarm_alert = 1; + optional int32 media_vol_steps = 2; + optional string notification_sound = 3; + optional string ringtone = 4; + optional int32 vc_call_vol_steps = 5; + + // Next Tag: 6 + } + optional Config config = 17; + + optional string control_privapp_permissions = 18; + optional int32 cp_system_other_odex = 19; + optional string crypto_scrypt_params = 20; + optional string crypto_state = 21; + optional string crypto_type = 22; + optional string dalvik_vm_native_bridge = 23; + optional int32 debuggable = 24; + optional string frp_pst = 25; + optional string gfx_driver_0 = 26; + + message Hardware { + option (stream_proto.stream_msg).enable_fields_mapping = true; + + optional string value = 1; // value of ro.hardware itself + + optional string activity_recognition = 2; + optional string audio = 3; + optional string audio_policy = 4; + optional string audio_a2dp = 5; + optional string audio_primary = 6; + optional string audio_usb = 7; + optional string bootctrl = 8; + optional string camera = 9; + optional string consumerir = 10; + optional string context_hub = 11; + optional string egl = 12; + optional string fingerprint = 13; + optional string flp = 14; + optional string gatekeeper = 15; + optional string gps = 16; + optional string gralloc = 17; + optional string hdmi_cec = 18; + optional string hwcomposer = 19; + optional string input = 20; + optional string keystore = 21; + optional string lights = 22; + optional string local_time = 23; + optional string memtrack = 24; + optional string nfc = 25; + optional string nfc_nci = 26; + optional string nfc_tag = 27; + optional string nvram = 28; + optional string power = 29; + optional string radio = 30; + optional string sensors = 31; + optional string sound_trigger = 32; + optional string thermal = 33; + optional string tv_input = 34; + optional string type = 35; + optional string vehicle = 36; + optional string vibrator = 37; + optional string virtual_device = 38; + optional string vulkan = 39; + + // Next Tag: 40 + } + optional Hardware hardware = 27; + + optional int32 kernel_qemu = 28; + optional int32 kernel_qemu_gles = 29; + optional int32 oem_unlock_supported = 30; + optional int32 opengles_version = 31; + + message Product { + option (stream_proto.stream_msg).enable_fields_mapping = true; + + optional string board = 1; + optional string brand = 2; + optional string cpu_abi = 3; + optional string cpu_abilist = 4; + optional string cpu_abilist32 = 5; + optional string cpu_abilist64 = 6; + optional string device = 7; + optional int32 first_api_level = 8; + optional string manufacturer = 9; + optional string model = 10; + optional string name = 11; + optional string vendor_brand = 12; + optional string vendor_device = 13; + optional string vendor_manufacturer = 14; + optional string vendor_model = 15; + optional string vendor_name = 16; + + // Next Tag: 17 + } + optional Product product = 32; + + optional int32 property_service_version = 33; + optional string retaildemo_video_path = 34; + optional string revision = 35; + optional int32 sf_lcd_density = 36; + optional bool storage_manager_enabled = 37; + optional bool telephony_call_ring_multiple = 38; + optional int32 telephony_default_cdma_sub = 39; + optional int32 telephony_default_network = 40; + optional string url_legal = 41; + optional string url_legal_android_privacy = 42; + optional string vendor_build_date = 43; + optional int32 vendor_build_date_utc = 44; + optional string vendor_build_fingerprint = 45; + optional string vndk_version = 46; + optional int32 vts_coverage = 47; + optional string zygote = 48; + + // Next Tag: 49 + } + optional Ro ro = 25; + + optional string sendbug_preferred_domain = 26; + optional int32 service_bootanim_exit = 27; + + message Sys { + option (stream_proto.stream_msg).enable_fields_mapping = true; + + optional int32 boot_completed = 1; + optional int32 boot_from_charger_mode = 2; + optional int32 retaildemo_enabled = 3; + optional string shutdown_requested = 4; + + message Usb { + option (stream_proto.stream_msg).enable_fields_mapping = true; + + optional string config = 1; + optional int32 configfs = 2; + optional string controller = 3; + optional int32 ffs_max_read = 4; + optional int32 ffs_max_write = 5; + optional int32 ffs_mtp_ready = 6; + optional int32 ffs_ready = 7; + optional int32 mtp_device_type = 8; + optional string state = 9; + + // Next Tag: 10 + } + optional Usb usb = 5; + + // Next Tag: 6 + } + optional Sys sys = 28; + + optional int32 telephony_lteOnCdmaDevice = 29; + optional int32 tombstoned_max_tombstone_count = 30; + optional string vold_decrypt = 31; + optional int32 vold_post_fs_data_done = 32; + optional int32 vts_native_server_on = 33; + optional string wifi_direct_interface = 34; + optional string wifi_interface = 35; + + // Next Tag: 36 } diff --git a/core/proto/android/server/alarmmanagerservice.proto b/core/proto/android/server/alarmmanagerservice.proto index d72443711edb..87d302e7e6a2 100644 --- a/core/proto/android/server/alarmmanagerservice.proto +++ b/core/proto/android/server/alarmmanagerservice.proto @@ -37,71 +37,71 @@ message AlarmManagerServiceProto { // Dump from ForceAppStandbyTracker. optional ForceAppStandbyTrackerProto force_app_standby_tracker = 6; - optional bool is_interactive = 8; + optional bool is_interactive = 7; // Only valid if is_interactive is false. - optional int64 time_since_non_interactive_ms = 9; + optional int64 time_since_non_interactive_ms = 8; // Only valid if is_interactive is false. - optional int64 max_wakeup_delay_ms = 10; + optional int64 max_wakeup_delay_ms = 9; // Only valid if is_interactive is false. - optional int64 time_since_last_dispatch_ms = 11; + optional int64 time_since_last_dispatch_ms = 10; // Only valid if is_interactive is false. - optional int64 time_until_next_non_wakeup_delivery_ms = 12; + optional int64 time_until_next_non_wakeup_delivery_ms = 11; - optional int64 time_until_next_non_wakeup_alarm_ms = 13; - optional int64 time_until_next_wakeup_ms = 14; - optional int64 time_since_last_wakeup_ms = 15; + optional int64 time_until_next_non_wakeup_alarm_ms = 12; + optional int64 time_until_next_wakeup_ms = 13; + optional int64 time_since_last_wakeup_ms = 14; // Time since the last wakeup was set. - optional int64 time_since_last_wakeup_set_ms = 16; - optional int64 time_change_event_count = 17; + optional int64 time_since_last_wakeup_set_ms = 15; + optional int64 time_change_event_count = 16; // The current set of user whitelisted apps for device idle mode, meaning // these are allowed to freely schedule alarms. These are app IDs, not UIDs. - repeated int32 device_idle_user_whitelist_app_ids = 18; + repeated int32 device_idle_user_whitelist_app_ids = 17; - repeated AlarmClockMetadataProto next_alarm_clock_metadata = 19; + repeated AlarmClockMetadataProto next_alarm_clock_metadata = 18; - repeated BatchProto pending_alarm_batches = 20; + repeated BatchProto pending_alarm_batches = 19; // List of alarms per uid deferred due to user applied background restrictions // on the source app. - repeated AlarmProto pending_user_blocked_background_alarms = 21; + repeated AlarmProto pending_user_blocked_background_alarms = 20; // When idling mode will end. Will be empty if the device is not currently // idling. - optional AlarmProto pending_idle_until = 22; + optional AlarmProto pending_idle_until = 21; // Any alarms that we don't want to run during idle mode. Will be empty if the // device is not currently idling. - repeated AlarmProto pending_while_idle_alarms = 23; + repeated AlarmProto pending_while_idle_alarms = 22; // This is a special alarm that will put the system into idle until it goes // off. The caller has given the time they want this to happen at. - optional AlarmProto next_wake_from_idle = 24; + optional AlarmProto next_wake_from_idle = 23; - repeated AlarmProto past_due_non_wakeup_alarms = 25; + repeated AlarmProto past_due_non_wakeup_alarms = 24; // Number of delayed alarms. - optional int32 delayed_alarm_count = 26; + optional int32 delayed_alarm_count = 25; // The total amount of time alarms had been delayed. Overlapping alarms are // only counted once (ie. If two alarms were meant to trigger at the same time // but were delayed by 5 seconds, the total time would be 5 seconds). - optional int64 total_delay_time_ms = 27; - optional int64 max_delay_duration_ms = 28; - optional int64 max_non_interactive_duration_ms = 29; + optional int64 total_delay_time_ms = 26; + optional int64 max_delay_duration_ms = 27; + optional int64 max_non_interactive_duration_ms = 28; - optional int32 broadcast_ref_count = 30; + optional int32 broadcast_ref_count = 29; // Canonical count of (operation.send() - onSendFinished()) and listener // send/complete/timeout invocations. - optional int32 pending_intent_send_count = 31; - optional int32 pending_intent_finish_count = 32; - optional int32 listener_send_count = 33; - optional int32 listener_finish_count = 34; + optional int32 pending_intent_send_count = 30; + optional int32 pending_intent_finish_count = 31; + optional int32 listener_send_count = 32; + optional int32 listener_finish_count = 33; - repeated InFlightProto outstanding_deliveries = 35; + repeated InFlightProto outstanding_deliveries = 34; // Minimum time between ALLOW_WHILE_IDLE alarms when system is idling. It // should be either CosntantsProto.allow_while_idle_short_duration_ms or // ConstantsProto.allow_while_idle_long_duration_ms. - optional int64 allow_while_idle_min_duration_ms = 36; + optional int64 allow_while_idle_min_duration_ms = 35; message LastAllowWhileIdleDispatch { optional int32 uid = 1; @@ -110,25 +110,25 @@ message AlarmManagerServiceProto { } // For each uid, this is the last time we dispatched an "allow while idle" // alarm, used to determine the earliest we can dispatch the next such alarm. - repeated LastAllowWhileIdleDispatch last_allow_while_idle_dispatch_times = 37; + repeated LastAllowWhileIdleDispatch last_allow_while_idle_dispatch_times = 36; - optional com.android.internal.util.LocalLogProto recent_problems = 38; + optional com.android.internal.util.LocalLogProto recent_problems = 37; message TopAlarm { optional int32 uid = 1; optional string package_name = 2; optional FilterStatsProto filter = 3; } - repeated TopAlarm top_alarms = 39; + repeated TopAlarm top_alarms = 38; message AlarmStat { optional BroadcastStatsProto broadcast = 1; repeated FilterStatsProto filters = 2; } - repeated AlarmStat alarm_stats = 40; + repeated AlarmStat alarm_stats = 39; - repeated IdleDispatchEntryProto allow_while_idle_dispatches = 41; - repeated WakeupEventProto recent_wakeup_history = 42; + repeated IdleDispatchEntryProto allow_while_idle_dispatches = 40; + repeated WakeupEventProto recent_wakeup_history = 41; } // This is a soft wrapper for alarm clock information. It is not representative @@ -145,8 +145,9 @@ message AlarmClockMetadataProto { message AlarmProto { optional string tag = 1; optional .android.app.AlarmManagerProto.AlarmType type = 2; - // How long until the alarm goes off, in the 'elapsed' timebase. - optional int64 when_elapsed_ms = 3; + // How long until the alarm goes off, in the 'elapsed' timebase. Can be + // negative if 'when' is in the past. + optional int64 time_until_when_elapsed_ms = 3; optional int64 window_length_ms = 4; optional int64 repeat_interval_ms = 5; optional int32 count = 6; diff --git a/core/proto/android/service/graphicsstats.proto b/core/proto/android/service/graphicsstats.proto index ee9d6fc7c05d..801411dbed13 100644 --- a/core/proto/android/service/graphicsstats.proto +++ b/core/proto/android/service/graphicsstats.proto @@ -31,7 +31,7 @@ message GraphicsStatsProto { optional string package_name = 1; // The version code of the app - optional int32 version_code = 2; + optional int64 version_code = 2; // The start & end timestamps in UTC as // milliseconds since January 1, 1970 diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 09204261811d..15e439ed3586 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -407,6 +407,7 @@ <protected-broadcast android:name="android.internal.policy.action.BURN_IN_PROTECTION" /> <protected-broadcast android:name="android.app.action.SYSTEM_UPDATE_POLICY_CHANGED" /> <protected-broadcast android:name="android.app.action.DEVICE_OWNER_CHANGED" /> + <protected-broadcast android:name="android.app.action.MANAGED_USER_CREATED" /> <!-- Added in N --> <protected-broadcast android:name="android.intent.action.ANR" /> @@ -2923,6 +2924,11 @@ <permission android:name="android.permission.BRIGHTNESS_SLIDER_USAGE" android:protectionLevel="signature|privileged" /> + <!-- Allows an application to modify the display brightness configuration + @hide --> + <permission android:name="android.permission.CONFIGURE_DISPLAY_BRIGHTNESS" + android:protectionLevel="signature|privileged|development" /> + <!-- @SystemApi Allows an application to control VPN. <p>Not for use by third-party applications.</p> @hide --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 0b38d1b1fca1..8377751f4236 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -963,12 +963,6 @@ --> <integer name="config_longPressOnBackBehavior">0</integer> - <!-- Control the behavior when the user panic presses the back button. - 0 - Nothing - 1 - Go to home - --> - <integer name="config_backPanicBehavior">0</integer> - <!-- Control the behavior when the user short presses the power button. 0 - Nothing 1 - Go to sleep (doze) @@ -1301,6 +1295,22 @@ <integer-array name="config_autoBrightnessLcdBacklightValues"> </integer-array> + <!-- Array of desired screen brightness in nits corresponding to the lux values + in the config_autoBrightnessLevels array. As with config_screenBrightnessMinimumNits and + config_screenBrightnessMaximumNits, the display brightness is defined as the measured + brightness of an all-white image. + + If this is defined then: + - config_autoBrightnessLcdBacklightValues should not be defined + - config_screenBrightnessMinimumNits must be defined + - config_screenBrightnessMaximumNits must be defined + + This array should have size one greater than the size of the config_autoBrightnessLevels + array. The brightness values must be non-negative and non-decreasing. This must be + overridden in platform specific overlays --> + <array name="config_autoBrightnessDisplayValuesNits"> + </array> + <!-- Array of output values for button backlight corresponding to the LUX values in the config_autoBrightnessLevels array. This array should have size one greater than the size of the config_autoBrightnessLevels array. @@ -1337,6 +1347,29 @@ <item>200</item> </integer-array> + <!-- The minimum brightness of the display in nits. On OLED displays this should be measured + with an all white image while the display is fully on and the backlight is set to + config_screenBrightnessSettingMinimum or config_screenBrightnessSettingDark, whichever + is darker. + + If this and config_screenBrightnessMinimumNits are set, then the display's brightness + range is assumed to be linear between + (config_screenBrightnessSettingMinimum, config_screenBrightnessMinimumNits) and + (config_screenBrightnessSettingMaximum, config_screenBrightnessMaximumNits). --> + <item name="config_screenBrightnessMinimumNits" format="float" type="dimen">-1.0</item> + + <!-- The maximum brightness of the display in nits. On OLED displays this should be measured + with an all white image while the display is fully on and the "backlight" is set to + config_screenBrightnessSettingMaximum. Note that this value should *not* reflect the + maximum brightness value for any high brightness modes but only the maximum brightness + value obtainable in a sustainable manner. + + If this and config_screenBrightnessMinimumNits are set to something non-negative, then the + display's brightness range is assumed to be linear between + (config_screenBrightnessSettingMinimum, config_screenBrightnessMaximumNits) and + (config_screenBrightnessSettingMaximum, config_screenBrightnessMaximumNits). --> + <item name="config_screenBrightnessMaximumNits" format="float" type="dimen">-1.0</item> + <!-- Array of ambient lux threshold values. This is used for determining hysteresis constraint values by calculating the index to use for lookup and then setting the constraint value to the corresponding value of the array. The new brightening hysteresis constraint value @@ -1387,6 +1420,9 @@ <!-- True if WallpaperService is enabled --> <bool name="config_enableWallpaperService">true</bool> + <!-- Class name of WallpaperManagerService. --> + <string name="config_wallpaperManagerServiceName">com.android.server.wallpaper.WallpaperManagerService</string> + <!-- Enables the TimeZoneRuleManager service. This is the master switch for the updateable time zone update mechanism. --> <bool name="config_enableUpdateableTimeZoneRules">false</bool> diff --git a/core/res/res/values/disallowed_apps_managed_device.xml b/core/res/res/values/disallowed_apps_managed_device.xml new file mode 100644 index 000000000000..8940b15ccabb --- /dev/null +++ b/core/res/res/values/disallowed_apps_managed_device.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * 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. + */ +--> +<resources> + <!-- A list of apps to be removed from the managed device. --> + <string-array name="disallowed_apps_managed_device"> + </string-array> +</resources> diff --git a/core/res/res/values/disallowed_apps_managed_profile.xml b/core/res/res/values/disallowed_apps_managed_profile.xml new file mode 100644 index 000000000000..e3a513f4f096 --- /dev/null +++ b/core/res/res/values/disallowed_apps_managed_profile.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * 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. + */ +--> +<resources> + <!-- A list of apps to be removed from the managed profile. --> + <string-array name="disallowed_apps_managed_profile"> + </string-array> +</resources> diff --git a/core/res/res/values/disallowed_apps_managed_user.xml b/core/res/res/values/disallowed_apps_managed_user.xml new file mode 100644 index 000000000000..b7b645dc0780 --- /dev/null +++ b/core/res/res/values/disallowed_apps_managed_user.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * 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. + */ +--> +<resources> + <!-- A list of apps to be removed from the managed user. --> + <string-array name="disallowed_apps_managed_user"> + </string-array> +</resources> diff --git a/core/res/res/values/required_apps_managed_device.xml b/core/res/res/values/required_apps_managed_device.xml new file mode 100644 index 000000000000..0ac706f51a70 --- /dev/null +++ b/core/res/res/values/required_apps_managed_device.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * 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. + */ +--> +<resources> + <!-- A list of apps to be retained on the managed device. + Takes precedence over the disallowed apps lists. --> + <string-array name="required_apps_managed_device"> + <item>com.android.settings</item> + <item>com.android.contacts</item> + <item>com.android.dialer</item> + <item>com.android.stk</item> <!-- Required by com.android.phone by certain carriers --> + <item>com.android.providers.downloads</item> + <item>com.android.providers.downloads.ui</item> + <item>com.android.documentsui</item> + </string-array> +</resources> diff --git a/core/res/res/values/required_apps_managed_profile.xml b/core/res/res/values/required_apps_managed_profile.xml new file mode 100644 index 000000000000..a0b8492644ee --- /dev/null +++ b/core/res/res/values/required_apps_managed_profile.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * 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. + */ +--> +<resources> + <!-- A list of apps to be retained in the managed profile. + Takes precedence over the disallowed apps lists. --> + <string-array name="required_apps_managed_profile"> + <item>com.android.contacts</item> + <item>com.android.settings</item> + <item>com.android.providers.downloads</item> + <item>com.android.providers.downloads.ui</item> + <item>com.android.documentsui</item> + </string-array> +</resources> diff --git a/core/res/res/values/required_apps_managed_user.xml b/core/res/res/values/required_apps_managed_user.xml new file mode 100644 index 000000000000..e8fdb210805c --- /dev/null +++ b/core/res/res/values/required_apps_managed_user.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * 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. + */ +--> +<resources> + <!-- A list of apps to be retained on the managed user. + Takes precedence over the disallowed apps lists. --> + <string-array name="required_apps_managed_user"> + <item>com.android.settings</item> + <item>com.android.contacts</item> + <item>com.android.dialer</item> + <item>com.android.stk</item> <!-- Required by com.android.phone by certain carriers --> + <item>com.android.providers.downloads</item> + <item>com.android.providers.downloads.ui</item> + <item>com.android.documentsui</item> + </string-array> +</resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index f659360199ef..be7ce5fc7e57 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -287,6 +287,7 @@ <java-symbol type="bool" name="split_action_bar_is_narrow" /> <java-symbol type="bool" name="config_useVolumeKeySounds" /> <java-symbol type="bool" name="config_enableWallpaperService" /> + <java-symbol type="string" name="config_wallpaperManagerServiceName" /> <java-symbol type="bool" name="config_enableUpdateableTimeZoneRules" /> <java-symbol type="bool" name="config_timeZoneRulesUpdateTrackingEnabled" /> <java-symbol type="string" name="config_timeZoneRulesUpdaterPackage" /> @@ -424,7 +425,6 @@ <java-symbol type="integer" name="config_veryLongPressOnPowerBehavior" /> <java-symbol type="integer" name="config_veryLongPressTimeout" /> <java-symbol type="integer" name="config_longPressOnBackBehavior" /> - <java-symbol type="integer" name="config_backPanicBehavior" /> <java-symbol type="integer" name="config_lowMemoryKillerMinFreeKbytesAdjust" /> <java-symbol type="integer" name="config_lowMemoryKillerMinFreeKbytesAbsolute" /> <java-symbol type="integer" name="config_max_pan_devices" /> @@ -1213,6 +1213,18 @@ <java-symbol type="array" name="config_telephonyHardware" /> <java-symbol type="array" name="config_keySystemUuidMapping" /> <java-symbol type="array" name="config_gpsParameters" /> + <java-symbol type="array" name="required_apps_managed_user" /> + <java-symbol type="array" name="required_apps_managed_profile" /> + <java-symbol type="array" name="required_apps_managed_device" /> + <java-symbol type="array" name="disallowed_apps_managed_user" /> + <java-symbol type="array" name="disallowed_apps_managed_profile" /> + <java-symbol type="array" name="disallowed_apps_managed_device" /> + <java-symbol type="array" name="vendor_required_apps_managed_user" /> + <java-symbol type="array" name="vendor_required_apps_managed_profile" /> + <java-symbol type="array" name="vendor_required_apps_managed_device" /> + <java-symbol type="array" name="vendor_disallowed_apps_managed_user" /> + <java-symbol type="array" name="vendor_disallowed_apps_managed_profile" /> + <java-symbol type="array" name="vendor_disallowed_apps_managed_device" /> <java-symbol type="drawable" name="default_wallpaper" /> <java-symbol type="drawable" name="default_lock_wallpaper" /> @@ -3173,4 +3185,8 @@ <java-symbol type="string" name="global_action_logout" /> <java-symbol type="drawable" name="ic_logout" /> + + <java-symbol type="dimen" name="config_screenBrightnessMinimumNits" /> + <java-symbol type="dimen" name="config_screenBrightnessMaximumNits" /> + <java-symbol type="array" name="config_autoBrightnessDisplayValuesNits" /> </resources> diff --git a/core/res/res/values/vendor_disallowed_apps_managed_device.xml b/core/res/res/values/vendor_disallowed_apps_managed_device.xml new file mode 100644 index 000000000000..c826d27d371e --- /dev/null +++ b/core/res/res/values/vendor_disallowed_apps_managed_device.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * 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. + */ +--> +<resources> + <!-- A list of apps to be removed from the managed device by a particular vendor. --> + <string-array name="vendor_disallowed_apps_managed_device"> + </string-array> +</resources> diff --git a/core/res/res/values/vendor_disallowed_apps_managed_profile.xml b/core/res/res/values/vendor_disallowed_apps_managed_profile.xml new file mode 100644 index 000000000000..5fcb2778b6bc --- /dev/null +++ b/core/res/res/values/vendor_disallowed_apps_managed_profile.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * 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. + */ +--> +<resources> + <!-- A list of apps to be removed from the managed profile by a particular vendor. --> + <string-array name="vendor_disallowed_apps_managed_profile"> + </string-array> +</resources> diff --git a/core/res/res/values/vendor_disallowed_apps_managed_user.xml b/core/res/res/values/vendor_disallowed_apps_managed_user.xml new file mode 100644 index 000000000000..3355d77aac6a --- /dev/null +++ b/core/res/res/values/vendor_disallowed_apps_managed_user.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * 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. + */ +--> +<resources> + <!-- A list of apps to be removed from the managed user by a particular vendor. --> + <string-array name="vendor_disallowed_apps_managed_user"> + </string-array> +</resources> diff --git a/core/res/res/values/vendor_required_apps_managed_device.xml b/core/res/res/values/vendor_required_apps_managed_device.xml new file mode 100644 index 000000000000..e684e22d8599 --- /dev/null +++ b/core/res/res/values/vendor_required_apps_managed_device.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * 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. + */ +--> +<resources> + <!-- A list of apps to be retained on the managed device by a particular vendor. + Takes precedence over the disallowed apps lists. --> + <string-array name="vendor_required_apps_managed_device"> + </string-array> +</resources> diff --git a/core/res/res/values/vendor_required_apps_managed_profile.xml b/core/res/res/values/vendor_required_apps_managed_profile.xml new file mode 100644 index 000000000000..4a3edf80c6e7 --- /dev/null +++ b/core/res/res/values/vendor_required_apps_managed_profile.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * 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. + */ +--> +<resources> + <!-- A list of apps to be retained in the managed profile by a particular vendor. + Takes precedence over the disallowed apps lists. --> + <string-array name="vendor_required_apps_managed_profile"> + </string-array> +</resources> diff --git a/core/res/res/values/vendor_required_apps_managed_user.xml b/core/res/res/values/vendor_required_apps_managed_user.xml new file mode 100644 index 000000000000..71dbd62f963c --- /dev/null +++ b/core/res/res/values/vendor_required_apps_managed_user.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * 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. + */ +--> +<resources> + <!-- A list of apps to be retained on the managed user by a particular vendor. + Takes precedence over the disallowed apps lists. --> + <string-array name="vendor_required_apps_managed_user"> + </string-array> +</resources> diff --git a/core/tests/coretests/assets/fonts/LineBreakingOverhangsTestFont.ttf b/core/tests/coretests/assets/fonts/LineBreakingOverhangsTestFont.ttf Binary files differdeleted file mode 100644 index cf769ed3e8a7..000000000000 --- a/core/tests/coretests/assets/fonts/LineBreakingOverhangsTestFont.ttf +++ /dev/null diff --git a/core/tests/coretests/assets/fonts/LineBreakingOverhangsTestFont.ttx b/core/tests/coretests/assets/fonts/LineBreakingOverhangsTestFont.ttx deleted file mode 100644 index 04d85922a977..000000000000 --- a/core/tests/coretests/assets/fonts/LineBreakingOverhangsTestFont.ttx +++ /dev/null @@ -1,234 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- 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. ---> -<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.9"> - - <GlyphOrder> - <!-- The 'id' attribute is only for humans; it is ignored when parsed. --> - <GlyphID id="0" name=".notdef"/> - <GlyphID id="1" name="space"/> - <GlyphID id="2" name="R"/> - <GlyphID id="3" name="a"/> - <GlyphID id="4" name="y"/> - </GlyphOrder> - - <head> - <!-- Most of this table will be recalculated by the compiler --> - <tableVersion value="1.0"/> - <fontRevision value="1.0"/> - <checkSumAdjustment value="0x26d0d624"/> - <magicNumber value="0x5f0f3cf5"/> - <flags value="00000000 00000011"/> - <unitsPerEm value="1000"/> - <created value="Tue Oct 3 23:00:00 2017"/> - <modified value="Tue Oct 3 23:33:15 2017"/> - <xMin value="-1500"/> - <yMin value="0"/> - <xMax value="5000"/> - <yMax value="1000"/> - <macStyle value="00000000 00000000"/> - <lowestRecPPEM value="7"/> - <fontDirectionHint value="2"/> - <indexToLocFormat value="0"/> - <glyphDataFormat value="0"/> - </head> - - <hhea> - <tableVersion value="0x00010000"/> - <ascent value="1000"/> - <descent value="-200"/> - <lineGap value="0"/> - <advanceWidthMax value="1000"/> - <minLeftSideBearing value="-1500"/> - <minRightSideBearing value="-4000"/> - <xMaxExtent value="5000"/> - <caretSlopeRise value="1"/> - <caretSlopeRun value="0"/> - <caretOffset value="0"/> - <reserved0 value="0"/> - <reserved1 value="0"/> - <reserved2 value="0"/> - <reserved3 value="0"/> - <metricDataFormat value="0"/> - <numberOfHMetrics value="1"/> - </hhea> - - <maxp> - <!-- Most of this table will be recalculated by the compiler --> - <tableVersion value="0x10000"/> - <numGlyphs value="5"/> - <maxPoints value="4"/> - <maxContours value="1"/> - <maxCompositePoints value="0"/> - <maxCompositeContours value="0"/> - <maxZones value="0"/> - <maxTwilightPoints value="0"/> - <maxStorage value="0"/> - <maxFunctionDefs value="0"/> - <maxInstructionDefs value="0"/> - <maxStackElements value="0"/> - <maxSizeOfInstructions value="0"/> - <maxComponentElements value="0"/> - <maxComponentDepth value="0"/> - </maxp> - - <OS_2> - <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex' - will be recalculated by the compiler --> - <version value="3"/> - <xAvgCharWidth value="594"/> - <usWeightClass value="400"/> - <usWidthClass value="5"/> - <fsType value="00000000 00001000"/> - <ySubscriptXSize value="650"/> - <ySubscriptYSize value="600"/> - <ySubscriptXOffset value="0"/> - <ySubscriptYOffset value="75"/> - <ySuperscriptXSize value="650"/> - <ySuperscriptYSize value="600"/> - <ySuperscriptXOffset value="0"/> - <ySuperscriptYOffset value="350"/> - <yStrikeoutSize value="50"/> - <yStrikeoutPosition value="300"/> - <sFamilyClass value="0"/> - <panose> - <bFamilyType value="0"/> - <bSerifStyle value="0"/> - <bWeight value="5"/> - <bProportion value="0"/> - <bContrast value="0"/> - <bStrokeVariation value="0"/> - <bArmStyle value="0"/> - <bLetterForm value="0"/> - <bMidline value="0"/> - <bXHeight value="0"/> - </panose> - <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/> - <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/> - <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/> - <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/> - <achVendID value="UKWN"/> - <fsSelection value="00000000 01000000"/> - <usFirstCharIndex value="32"/> - <usLastCharIndex value="121"/> - <sTypoAscender value="800"/> - <sTypoDescender value="-200"/> - <sTypoLineGap value="200"/> - <usWinAscent value="1000"/> - <usWinDescent value="200"/> - <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/> - <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/> - <sxHeight value="500"/> - <sCapHeight value="700"/> - <usDefaultChar value="0"/> - <usBreakChar value="32"/> - <usMaxContext value="0"/> - </OS_2> - - <hmtx> - <mtx name=".notdef" width="1000" lsb="0"/> - <mtx name="R" width="1000" lsb="0"/> - <mtx name="a" width="1000" lsb="0"/> - <mtx name="space" width="1000" lsb="0"/> - <mtx name="y" width="1000" lsb="-1500"/> - </hmtx> - - <cmap> - <tableVersion version="0"/> - <cmap_format_12 platformID="3" platEncID="10" format="12" reserved="0" length="64" language="0" nGroups="4"> - <map code="0x20" name="space"/><!-- SPACE --> - <map code="0x52" name="R"/><!-- LATIN CAPITAL LETTER R --> - <map code="0x61" name="a"/><!-- LATIN SMALL LETTER A --> - <map code="0x79" name="y"/><!-- LATIN SMALL LETTER Y --> - </cmap_format_12> - </cmap> - - <loca> - <!-- The 'loca' table will be calculated by the compiler --> - </loca> - - <glyf> - - <!-- The xMin, yMin, xMax and yMax values - will be recalculated by the compiler. --> - - <TTGlyph name=".notdef"/><!-- contains no outline data --> - - <TTGlyph name="R" xMin="0" yMin="0" xMax="5000" yMax="1000"> - <contour> - <pt x="0" y="0" on="1"/> - <pt x="0" y="1000" on="1"/> - <pt x="5000" y="1000" on="1"/> - <pt x="5000" y="0" on="1"/> - </contour> - <instructions/> - </TTGlyph> - - <TTGlyph name="a"/><!-- contains no outline data --> - - <TTGlyph name="space"/><!-- contains no outline data --> - - <TTGlyph name="y" xMin="-1500" yMin="0" xMax="1000" yMax="1000"> - <contour> - <pt x="-1500" y="0" on="1"/> - <pt x="-1500" y="1000" on="1"/> - <pt x="1000" y="1000" on="1"/> - <pt x="1000" y="0" on="1"/> - </contour> - <instructions/> - </TTGlyph> - - </glyf> - - <name> - <namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True"> - Font for LineBreakingOverhangsTest - </namerecord> - <namerecord nameID="2" platformID="1" platEncID="0" langID="0x0" unicode="True"> - Regular - </namerecord> - <namerecord nameID="4" platformID="1" platEncID="0" langID="0x0" unicode="True"> - Font for LineBreakingOverhangsTest - </namerecord> - <namerecord nameID="6" platformID="1" platEncID="0" langID="0x0" unicode="True"> - SampleFont-Regular - </namerecord> - <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409"> - Sample Font - </namerecord> - <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409"> - Regular - </namerecord> - <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409"> - Sample Font - </namerecord> - <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409"> - SampleFont-Regular - </namerecord> - </name> - - <post> - <formatType value="3.0"/> - <italicAngle value="0.0"/> - <underlinePosition value="-75"/> - <underlineThickness value="50"/> - <isFixedPitch value="0"/> - <minMemType42 value="0"/> - <maxMemType42 value="0"/> - <minMemType1 value="0"/> - <maxMemType1 value="0"/> - </post> - -</ttFont> diff --git a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java new file mode 100644 index 000000000000..bad0d258a54c --- /dev/null +++ b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java @@ -0,0 +1,187 @@ +/* + * 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.hardware.display; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import android.os.Parcel; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; +import android.util.Pair; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Arrays; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class BrightnessConfigurationTest { + private static final float[] LUX_LEVELS = { + 0f, + 10f, + 100f, + }; + + private static final float[] NITS_LEVELS = { + 0.5f, + 90f, + 100f, + }; + + @Test + public void testSetCurveIsUnmodified() { + BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(); + builder.setCurve(LUX_LEVELS, NITS_LEVELS); + BrightnessConfiguration config = builder.build(); + Pair<float[], float[]> curve = config.getCurve(); + assertArrayEquals(LUX_LEVELS, curve.first, "lux"); + assertArrayEquals(NITS_LEVELS, curve.second, "nits"); + } + + @Test(expected = IllegalArgumentException.class) + public void testCurveMustHaveZeroLuxPoint() { + BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(); + float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length); + lux[0] = 1f; + builder.setCurve(lux, NITS_LEVELS); + } + + @Test(expected = IllegalStateException.class) + public void testCurveMustBeSet() { + BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(); + builder.build(); + } + + @Test(expected = NullPointerException.class) + public void testCurveMustNotHaveNullArrays() { + BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(); + builder.setCurve(null, null); + } + + @Test(expected = IllegalArgumentException.class) + public void testCurveMustNotHaveEmptyArrays() { + BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(); + builder.setCurve(new float[0], new float[0]); + } + + @Test + public void testCurveMustNotHaveArraysOfDifferentLengths() { + assertThrows(IllegalArgumentException.class, () -> { + BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(); + float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length + 1); + lux[lux.length - 1] = lux[lux.length - 2] + 1; + boolean exceptionThrown = false; + builder.setCurve(lux, NITS_LEVELS); + }); + + assertThrows(IllegalArgumentException.class, () -> { + BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(); + float[] nits = Arrays.copyOf(NITS_LEVELS, NITS_LEVELS.length + 1); + nits[nits.length - 1] = nits[nits.length - 2] + 1; + builder.setCurve(LUX_LEVELS, nits); + }); + } + + @Test + public void testCurvesMustNotContainNaN() { + assertThrows(IllegalArgumentException.class, () -> { + float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length); + lux[lux.length - 1] = Float.NaN; + BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(); + builder.setCurve(lux, NITS_LEVELS); + }); + + assertThrows(IllegalArgumentException.class, () -> { + float[] nits = Arrays.copyOf(NITS_LEVELS, NITS_LEVELS.length); + nits[nits.length - 1] = Float.NaN; + BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(); + builder.setCurve(LUX_LEVELS, nits); + }); + } + + + @Test + public void testParceledConfigIsEquivalent() { + BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(); + builder.setCurve(LUX_LEVELS, NITS_LEVELS); + BrightnessConfiguration config = builder.build(); + Parcel p = Parcel.obtain(); + p.writeParcelable(config, 0 /*flags*/); + p.setDataPosition(0); + BrightnessConfiguration newConfig = + p.readParcelable(BrightnessConfiguration.class.getClassLoader()); + assertEquals(config, newConfig); + } + + @Test + public void testEquals() { + BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(); + builder.setCurve(LUX_LEVELS, NITS_LEVELS); + BrightnessConfiguration baseConfig = builder.build(); + + builder = new BrightnessConfiguration.Builder(); + builder.setCurve(LUX_LEVELS, NITS_LEVELS); + BrightnessConfiguration identicalConfig = builder.build(); + assertEquals(baseConfig, identicalConfig); + assertEquals("hashCodes must be equal for identical configs", + baseConfig.hashCode(), identicalConfig.hashCode()); + + float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length); + lux[lux.length - 1] = lux[lux.length - 1] * 2; + builder = new BrightnessConfiguration.Builder(); + builder.setCurve(lux, NITS_LEVELS); + BrightnessConfiguration luxDifferConfig = builder.build(); + assertNotEquals(baseConfig, luxDifferConfig); + + float[] nits = Arrays.copyOf(NITS_LEVELS, NITS_LEVELS.length); + nits[nits.length - 1] = nits[nits.length - 1] * 2; + builder = new BrightnessConfiguration.Builder(); + builder.setCurve(LUX_LEVELS, nits); + BrightnessConfiguration nitsDifferConfig = builder.build(); + assertNotEquals(baseConfig, nitsDifferConfig); + } + + private static void assertArrayEquals(float[] expected, float[] actual, String name) { + assertEquals("Expected " + name + " arrays to be the same length!", + expected.length, actual.length); + for (int i = 0; i < expected.length; i++) { + assertEquals("Expected " + name + " arrays to be equivalent when value " + i + + "differs", expected[i], actual[i], 0.01 /*tolerance*/); + } + } + + private interface ExceptionRunnable { + void run() throws Exception; + } + + private static void assertThrows(Class<? extends Throwable> exceptionClass, + ExceptionRunnable r) { + try { + r.run(); + } catch (Throwable e) { + assertTrue("Expected exception type " + exceptionClass.getName() + " but got " + + e.getClass().getName(), exceptionClass.isAssignableFrom(e.getClass())); + return; + } + fail("Expected exception type " + exceptionClass.getName() + + ", but no exception was thrown"); + } +} diff --git a/core/tests/coretests/src/android/text/BidiFormatterTest.java b/core/tests/coretests/src/android/text/BidiFormatterTest.java index 14705add258f..1b936c7b1c1d 100644 --- a/core/tests/coretests/src/android/text/BidiFormatterTest.java +++ b/core/tests/coretests/src/android/text/BidiFormatterTest.java @@ -18,12 +18,14 @@ package android.text; import static org.junit.Assert.assertEquals; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class BidiFormatterTest { diff --git a/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java b/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java index 08e1b5bdcd6d..c69f4f58b44e 100644 --- a/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java +++ b/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java @@ -21,6 +21,7 @@ import static android.text.Layout.Alignment.ALIGN_NORMAL; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -33,6 +34,7 @@ import org.junit.runner.RunWith; * Requires disabling access checks in the vm since this calls package-private APIs. * */ +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class DynamicLayoutBlocksTest { diff --git a/core/tests/coretests/src/android/text/DynamicLayoutTest.java b/core/tests/coretests/src/android/text/DynamicLayoutTest.java index 639cefbcf26b..aa9aed8e2fcc 100644 --- a/core/tests/coretests/src/android/text/DynamicLayoutTest.java +++ b/core/tests/coretests/src/android/text/DynamicLayoutTest.java @@ -26,6 +26,7 @@ import static org.junit.Assert.assertTrue; import android.graphics.Canvas; import android.graphics.Paint; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.text.style.ReplacementSpan; @@ -33,6 +34,7 @@ import android.text.style.ReplacementSpan; import org.junit.Test; import org.junit.runner.RunWith; +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class DynamicLayoutTest { diff --git a/core/tests/coretests/src/android/text/LayoutTest.java b/core/tests/coretests/src/android/text/LayoutTest.java index 9cf8e1ee363d..2448b0b58f9c 100644 --- a/core/tests/coretests/src/android/text/LayoutTest.java +++ b/core/tests/coretests/src/android/text/LayoutTest.java @@ -29,6 +29,7 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.Rect; import android.graphics.RectF; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.text.Layout.Alignment; @@ -42,6 +43,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class LayoutTest { diff --git a/core/tests/coretests/src/android/text/LineBreakingOverhangsTest.java b/core/tests/coretests/src/android/text/LineBreakingOverhangsTest.java deleted file mode 100644 index 4f18b0b4c7a4..000000000000 --- a/core/tests/coretests/src/android/text/LineBreakingOverhangsTest.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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.text; - -import static org.junit.Assert.assertEquals; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.graphics.Typeface; -import android.support.test.InstrumentationRegistry; -import android.support.test.filters.SmallTest; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -@SmallTest -@RunWith(AndroidJUnit4.class) -public class LineBreakingOverhangsTest { - private static final int EM = 100; // Make 1em == 100px. - private static final TextPaint sTextPaint = new TextPaint(); - - static { - // The test font has following coverage and overhangs. - // All the characters have a width of 1em. - // space: no overhangs - // R: 4em overhang on the right - // a: no overhang - // y: 1.5em overhang on the left - sTextPaint.setTypeface(Typeface.createFromAsset( - InstrumentationRegistry.getTargetContext().getAssets(), - "fonts/LineBreakingOverhangsTestFont.ttf")); - sTextPaint.setTextSize(EM); - } - - private static void layout(@NonNull CharSequence source, @NonNull int[] breaks, double width, - @Nullable int[] leftPadding, @Nullable int[] rightPadding) { - layout(source, breaks, width, leftPadding, rightPadding, null /* indents */); - } - - private static void layout(@NonNull CharSequence source, @NonNull int[] breaks, double width, - @Nullable int[] leftPadding, @Nullable int[] rightPadding, @Nullable int[] indents) { - final StaticLayout staticLayout = StaticLayout.Builder - .obtain(source, 0, source.length(), sTextPaint, (int) width) - .setAvailablePaddings(leftPadding, rightPadding) - .setIndents(indents, indents) - .build(); - - final int lineCount = breaks.length + 1; - assertEquals("Number of lines", lineCount, staticLayout.getLineCount()); - - for (int line = 0; line < lineCount; line++) { - final int lineStart = staticLayout.getLineStart(line); - final int lineEnd = staticLayout.getLineEnd(line); - - if (line == 0) { - assertEquals("Line start for first line", 0, lineStart); - } else { - assertEquals("Line start for line " + line, breaks[line - 1], lineStart); - } - - if (line == lineCount - 1) { - assertEquals("Line end for last line", source.length(), lineEnd); - } else { - assertEquals("Line end for line " + line, breaks[line], lineEnd); - } - } - } - - private static final int[] NO_BREAK = new int[] {}; - - private static final int[] NO_PADDING = null; - // Maximum needed for left side of 'y'. - private static final int[] FULL_LEFT_PADDING = new int[] {(int) (1.5 * EM)}; - // Maximum padding needed for right side of 'R'. - private static final int[] FULL_RIGHT_PADDING = new int[] {4 * EM}; - - private static final int[] ONE_EM_PADDING = new int[] {1 * EM}; - private static final int[] HALF_EM_PADDING = new int[] {(int) (0.5 * EM)}; - private static final int[] QUARTER_EM_PADDING = new int[] {(int) (0.25 * EM)}; - - @Test - public void testRightOverhang() { - // The advance of "aaa R" is 5em, but the right-side overhang of 'R' would need 4em more, so - // we break the line if there's not enough overhang. - - // Enough right padding, so the whole line fits in 5em. - layout("aaa R", NO_BREAK, 5 * EM, NO_PADDING, FULL_RIGHT_PADDING); - - // No right padding, so we'd need 9em to fit the advance and the right padding of 'R'. - layout("aaa R", new int[] {4}, 8.9 * EM, NO_PADDING, NO_PADDING); - layout("aaa R", NO_BREAK, 9 * EM, NO_PADDING, NO_PADDING); - - // 1em of right padding means we can fit the string in 8em. - layout("aaa R", new int[] {4}, 7.9 * EM, NO_PADDING, ONE_EM_PADDING); - layout("aaa R", NO_BREAK, 8 * EM, NO_PADDING, ONE_EM_PADDING); - } - - @Test - public void testLeftOverhang() { - // The advance of "y a" is 3em, but the left-side overhang of 'y' would need 1.5em more, so - // we break the line if there's not enough overhang. - - // Enough left padding, so the whole line fits in 3em. - layout("y a", NO_BREAK, 3 * EM, FULL_LEFT_PADDING, NO_PADDING); - - // No right padding, so we'd need 4.5em to fit the advance and the left padding of 'y'. - layout("y a", new int[] {2}, 4.4 * EM, NO_PADDING, NO_PADDING); - layout("y a", NO_BREAK, 4.5 * EM, NO_PADDING, NO_PADDING); - - // 1em of left padding means we can fit the string in 3.5em. - layout("y a", new int[] {2}, 3.4 * EM, ONE_EM_PADDING, NO_PADDING); - layout("y a", NO_BREAK, 3.5 * EM, ONE_EM_PADDING, NO_PADDING); - } - - @Test - public void testBothSidesOverhang() { - // The advance of "y a R" is 5em, but the left-side overhang of 'y' would need 1.5em more, - // and the right side overhang or 'R' would need 4em more, so we break the line if there's - // not enough overhang. - - // Enough padding, so the whole line fits in 5em. - layout("y a R", NO_BREAK, 5 * EM, FULL_LEFT_PADDING, FULL_RIGHT_PADDING); - - // No padding, so we'd need 10.5em to fit the advance and the paddings. - layout("y a R", new int[] {4}, 10.4 * EM, NO_PADDING, NO_PADDING); - layout("y a R", NO_BREAK, 10.5 * EM, NO_PADDING, NO_PADDING); - - // 1em of padding on each side means we can fit the string in 8.5em. - layout("y a R", new int[] {4}, 8.4 * EM, ONE_EM_PADDING, ONE_EM_PADDING); - layout("y a R", NO_BREAK, 8.5 * EM, ONE_EM_PADDING, ONE_EM_PADDING); - } - - @Test - public void testIndentsDontAffectPaddings() { - // This is identical to the previous test, except that it applies wide indents of 4em on - // each side and thus needs an extra 8em of width. This test makes sure that indents and - // paddings are independent. - final int[] indents = new int[] {4 * EM}; - final int indentAdj = 8 * EM; - - // Enough padding, so the whole line fits in 5em. - layout("y a R", NO_BREAK, 5 * EM + indentAdj, FULL_LEFT_PADDING, FULL_RIGHT_PADDING, - indents); - - // No padding, so we'd need 10.5em to fit the advance and the paddings. - layout("y a R", new int[] {4}, 10.4 * EM + indentAdj, NO_PADDING, NO_PADDING, indents); - layout("y a R", NO_BREAK, 10.5 * EM + indentAdj, NO_PADDING, NO_PADDING, indents); - - // 1em of padding on each side means we can fit the string in 8.5em. - layout("y a R", new int[] {4}, 8.4 * EM + indentAdj, ONE_EM_PADDING, ONE_EM_PADDING, - indents); - layout("y a R", NO_BREAK, 8.5 * EM + indentAdj, ONE_EM_PADDING, ONE_EM_PADDING, indents); - } -} diff --git a/core/tests/coretests/src/android/text/PackedIntVectorTest.java b/core/tests/coretests/src/android/text/PackedIntVectorTest.java index 9df0f8911893..d9dc6fc44495 100644 --- a/core/tests/coretests/src/android/text/PackedIntVectorTest.java +++ b/core/tests/coretests/src/android/text/PackedIntVectorTest.java @@ -18,6 +18,7 @@ package android.text; import static org.junit.Assert.assertEquals; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -27,6 +28,7 @@ import org.junit.runner.RunWith; /** * PackedIntVectorTest tests the features of android.util.PackedIntVector. */ +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class PackedIntVectorTest { diff --git a/core/tests/coretests/src/android/text/SpannableStringBuilderTest.java b/core/tests/coretests/src/android/text/SpannableStringBuilderTest.java index 04a486eb7cda..f1a730a7a420 100644 --- a/core/tests/coretests/src/android/text/SpannableStringBuilderTest.java +++ b/core/tests/coretests/src/android/text/SpannableStringBuilderTest.java @@ -20,13 +20,18 @@ package android.text; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; import android.text.style.BulletSpan; import android.text.style.QuoteSpan; import android.text.style.SubscriptSpan; import android.text.style.UnderlineSpan; import org.junit.Test; +import org.junit.runner.RunWith; +@SmallTest +@RunWith(AndroidJUnit4.class) public class SpannableStringBuilderTest extends SpannableTest { protected Spannable newSpannableWithText(String text) { diff --git a/core/tests/coretests/src/android/text/SpannableTest.java b/core/tests/coretests/src/android/text/SpannableTest.java index 5ed6250fbc60..307ac62f9d07 100644 --- a/core/tests/coretests/src/android/text/SpannableTest.java +++ b/core/tests/coretests/src/android/text/SpannableTest.java @@ -16,14 +16,16 @@ package android.text; -import android.support.test.filters.MediumTest; +import android.platform.test.annotations.Presubmit; +import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.test.MoreAsserts; import org.junit.Test; import org.junit.runner.RunWith; -@MediumTest +@Presubmit +@SmallTest @RunWith(AndroidJUnit4.class) public abstract class SpannableTest { diff --git a/core/tests/coretests/src/android/text/SpannedTest.java b/core/tests/coretests/src/android/text/SpannedTest.java index 60cddb08e0d7..573757165101 100644 --- a/core/tests/coretests/src/android/text/SpannedTest.java +++ b/core/tests/coretests/src/android/text/SpannedTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals; import android.graphics.Typeface; import android.os.Parcel; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.text.style.CharacterStyle; @@ -33,6 +34,7 @@ import org.junit.runner.RunWith; /** * SpannedTest tests some features of Spanned */ +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class SpannedTest { diff --git a/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java b/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java index 8092203033c2..bf0d42788b72 100644 --- a/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java +++ b/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java @@ -18,6 +18,7 @@ package android.text; import static org.junit.Assert.assertEquals; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.util.Log; @@ -28,6 +29,7 @@ import org.junit.runner.RunWith; /** * Quick check of native bidi implementation. */ +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class StaticLayoutBidiTest { diff --git a/core/tests/coretests/src/android/text/StaticLayoutDirectionsTest.java b/core/tests/coretests/src/android/text/StaticLayoutDirectionsTest.java index e0b47765a625..5cf54268e004 100644 --- a/core/tests/coretests/src/android/text/StaticLayoutDirectionsTest.java +++ b/core/tests/coretests/src/android/text/StaticLayoutDirectionsTest.java @@ -18,16 +18,19 @@ package android.text; import static org.junit.Assert.fail; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.text.Layout.Directions; import android.text.StaticLayoutTest.LayoutBuilder; -import java.util.Arrays; -import java.util.Formatter; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.Arrays; +import java.util.Formatter; + +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class StaticLayoutDirectionsTest { diff --git a/core/tests/coretests/src/android/text/StaticLayoutTest.java b/core/tests/coretests/src/android/text/StaticLayoutTest.java index 078ed76844ac..f4514b56ec8d 100644 --- a/core/tests/coretests/src/android/text/StaticLayoutTest.java +++ b/core/tests/coretests/src/android/text/StaticLayoutTest.java @@ -24,6 +24,7 @@ import static org.junit.Assert.assertTrue; import android.graphics.Canvas; import android.graphics.Paint.FontMetricsInt; import android.os.LocaleList; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.text.Layout.Alignment; @@ -43,6 +44,7 @@ import java.util.Locale; /** * Tests StaticLayout vertical metrics behavior. */ +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class StaticLayoutTest { diff --git a/core/tests/coretests/src/android/text/TextLayoutTest.java b/core/tests/coretests/src/android/text/TextLayoutTest.java index 896318987d94..24020ceb0cd4 100644 --- a/core/tests/coretests/src/android/text/TextLayoutTest.java +++ b/core/tests/coretests/src/android/text/TextLayoutTest.java @@ -16,6 +16,7 @@ package android.text; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -23,6 +24,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class TextLayoutTest { diff --git a/core/tests/coretests/src/android/text/TextLineTest.java b/core/tests/coretests/src/android/text/TextLineTest.java index f8d688498b5f..d9c09c8b03bf 100644 --- a/core/tests/coretests/src/android/text/TextLineTest.java +++ b/core/tests/coretests/src/android/text/TextLineTest.java @@ -19,6 +19,7 @@ package android.text; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.filters.Suppress; import android.support.test.runner.AndroidJUnit4; @@ -26,6 +27,7 @@ import android.support.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class TextLineTest { diff --git a/core/tests/coretests/src/android/text/TextUtilsTest.java b/core/tests/coretests/src/android/text/TextUtilsTest.java index 79619d9a49db..e70b8412ac65 100644 --- a/core/tests/coretests/src/android/text/TextUtilsTest.java +++ b/core/tests/coretests/src/android/text/TextUtilsTest.java @@ -25,6 +25,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import android.os.Parcel; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.LargeTest; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -46,6 +47,7 @@ import java.util.Locale; /** * TextUtilsTest tests {@link TextUtils}. */ +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class TextUtilsTest { diff --git a/core/tests/coretests/src/android/text/VariationParserTest.java b/core/tests/coretests/src/android/text/VariationParserTest.java index ec2c96cdeeff..fbd2412a35cc 100644 --- a/core/tests/coretests/src/android/text/VariationParserTest.java +++ b/core/tests/coretests/src/android/text/VariationParserTest.java @@ -20,12 +20,14 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import android.graphics.fonts.FontVariationAxis; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class VariationParserTest { diff --git a/core/tests/coretests/src/android/text/format/DateFormatTest.java b/core/tests/coretests/src/android/text/format/DateFormatTest.java index 0f08d183c14b..9000ed07d606 100644 --- a/core/tests/coretests/src/android/text/format/DateFormatTest.java +++ b/core/tests/coretests/src/android/text/format/DateFormatTest.java @@ -19,6 +19,7 @@ package android.text.format; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -27,6 +28,7 @@ import org.junit.runner.RunWith; import java.util.Locale; +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class DateFormatTest { diff --git a/core/tests/coretests/src/android/text/format/DateUtilsTest.java b/core/tests/coretests/src/android/text/format/DateUtilsTest.java index f21c9297dde9..f8e3b4dfec56 100644 --- a/core/tests/coretests/src/android/text/format/DateUtilsTest.java +++ b/core/tests/coretests/src/android/text/format/DateUtilsTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertEquals; import android.content.res.Configuration; import android.content.res.Resources; import android.os.LocaleList; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -35,6 +36,7 @@ import java.util.Date; import java.util.Locale; import java.util.TimeZone; +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class DateUtilsTest { diff --git a/core/tests/coretests/src/android/text/format/FormatterTest.java b/core/tests/coretests/src/android/text/format/FormatterTest.java index dee51dcbc7ff..2d9401686e81 100644 --- a/core/tests/coretests/src/android/text/format/FormatterTest.java +++ b/core/tests/coretests/src/android/text/format/FormatterTest.java @@ -189,7 +189,7 @@ public class FormatterTest { // Make sure it works on different locales. setLocale(new Locale("ru", "RU")); - assertEquals("1 мин", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + assertEquals("1 мин.", Formatter.formatShortElapsedTimeRoundingUpToMinutes( mContext, 1 * SECOND)); } diff --git a/core/tests/coretests/src/android/text/format/TimeTest.java b/core/tests/coretests/src/android/text/format/TimeTest.java index 8983d15f0d19..d563f2e2383b 100644 --- a/core/tests/coretests/src/android/text/format/TimeTest.java +++ b/core/tests/coretests/src/android/text/format/TimeTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.filters.Suppress; import android.support.test.runner.AndroidJUnit4; @@ -29,6 +30,7 @@ import android.util.TimeFormatException; import org.junit.Test; import org.junit.runner.RunWith; +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class TimeTest { diff --git a/core/tests/coretests/src/android/text/method/BackspaceTest.java b/core/tests/coretests/src/android/text/method/BackspaceTest.java index 8b5cc60ddaea..df4609f5a728 100644 --- a/core/tests/coretests/src/android/text/method/BackspaceTest.java +++ b/core/tests/coretests/src/android/text/method/BackspaceTest.java @@ -16,6 +16,7 @@ package android.text.method; +import android.platform.test.annotations.Presubmit; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -24,6 +25,7 @@ import android.util.KeyUtils; import android.view.KeyEvent; import android.widget.EditText; import android.widget.TextView.BufferType; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -34,6 +36,8 @@ import org.junit.runner.RunWith; * Only contains edge cases. For normal cases, see {@see android.text.method.cts.BackspaceTest}. * TODO: introduce test cases for surrogate pairs and replacement span. */ + +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class BackspaceTest { diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java index c3a5f800daf9..15dbbc8de150 100644 --- a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java +++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java @@ -16,6 +16,7 @@ package android.text.method; +import android.platform.test.annotations.Presubmit; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -35,6 +36,7 @@ import org.junit.runner.RunWith; * Only contains edge cases. For normal cases, see {@see android.text.method.cts.ForwardDeleteTest}. * TODO: introduce test cases for surrogate pairs and replacement span. */ +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class ForwardDeleteTest { diff --git a/core/tests/coretests/src/android/text/method/WordIteratorTest.java b/core/tests/coretests/src/android/text/method/WordIteratorTest.java index d1f4f7e84c25..684586387255 100644 --- a/core/tests/coretests/src/android/text/method/WordIteratorTest.java +++ b/core/tests/coretests/src/android/text/method/WordIteratorTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -31,6 +32,7 @@ import java.text.BreakIterator; import java.util.Locale; // TODO(Bug: 24062099): Add more tests for non-ascii text. +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class WordIteratorTest { diff --git a/core/tests/coretests/src/android/text/style/UnderlineSpanTest.java b/core/tests/coretests/src/android/text/style/UnderlineSpanTest.java index e5c4b821c1cf..3d7e5bab15f3 100644 --- a/core/tests/coretests/src/android/text/style/UnderlineSpanTest.java +++ b/core/tests/coretests/src/android/text/style/UnderlineSpanTest.java @@ -19,6 +19,7 @@ package android.text.style; import static org.junit.Assert.assertEquals; +import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.text.SpannableString; @@ -29,7 +30,7 @@ import android.text.TextPaint; import org.junit.Test; import org.junit.runner.RunWith; - +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class UnderlineSpanTest { diff --git a/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java b/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java index e0664d940f4e..0fd0136a85ed 100644 --- a/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java +++ b/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java @@ -16,21 +16,33 @@ package android.view.inputmethod; +import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION; +import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION; +import static android.view.inputmethod.CursorAnchorInfo.FLAG_IS_RTL; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + import android.graphics.Matrix; import android.graphics.RectF; import android.os.Parcel; -import android.test.InstrumentationTestCase; -import android.test.suitebuilder.annotation.SmallTest; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; import android.text.TextUtils; import android.view.inputmethod.CursorAnchorInfo.Builder; +import org.junit.Test; +import org.junit.runner.RunWith; + import java.util.Objects; -import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION; -import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION; -import static android.view.inputmethod.CursorAnchorInfo.FLAG_IS_RTL; +@SmallTest +@RunWith(AndroidJUnit4.class) +public class CursorAnchorInfoTest { + private static final float EPSILON = 0.0000001f; -public class CursorAnchorInfoTest extends InstrumentationTestCase { private static final RectF[] MANY_BOUNDS = new RectF[] { new RectF(101.0f, 201.0f, 301.0f, 401.0f), new RectF(102.0f, 202.0f, 302.0f, 402.0f), @@ -74,7 +86,7 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL, }; - @SmallTest + @Test public void testBuilder() throws Exception { final int SELECTION_START = 30; final int SELECTION_END = 40; @@ -109,10 +121,10 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { assertEquals(COMPOSING_TEXT_START, info.getComposingTextStart()); assertTrue(TextUtils.equals(COMPOSING_TEXT, info.getComposingText())); assertEquals(INSERTION_MARKER_FLAGS, info.getInsertionMarkerFlags()); - assertEquals(INSERTION_MARKER_HORIZONTAL, info.getInsertionMarkerHorizontal()); - assertEquals(INSERTION_MARKER_TOP, info.getInsertionMarkerTop()); - assertEquals(INSERTION_MARKER_BASELINE, info.getInsertionMarkerBaseline()); - assertEquals(INSERTION_MARKER_BOTOM, info.getInsertionMarkerBottom()); + assertEquals(INSERTION_MARKER_HORIZONTAL, info.getInsertionMarkerHorizontal(), EPSILON); + assertEquals(INSERTION_MARKER_TOP, info.getInsertionMarkerTop(), EPSILON); + assertEquals(INSERTION_MARKER_BASELINE, info.getInsertionMarkerBaseline(), EPSILON); + assertEquals(INSERTION_MARKER_BOTOM, info.getInsertionMarkerBottom(), EPSILON); assertEquals(TRANSFORM_MATRIX, info.getMatrix()); for (int i = 0; i < MANY_BOUNDS.length; i++) { final RectF expectedBounds = MANY_BOUNDS[i]; @@ -134,10 +146,10 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { assertEquals(COMPOSING_TEXT_START, info2.getComposingTextStart()); assertTrue(TextUtils.equals(COMPOSING_TEXT, info2.getComposingText())); assertEquals(INSERTION_MARKER_FLAGS, info2.getInsertionMarkerFlags()); - assertEquals(INSERTION_MARKER_HORIZONTAL, info2.getInsertionMarkerHorizontal()); - assertEquals(INSERTION_MARKER_TOP, info2.getInsertionMarkerTop()); - assertEquals(INSERTION_MARKER_BASELINE, info2.getInsertionMarkerBaseline()); - assertEquals(INSERTION_MARKER_BOTOM, info2.getInsertionMarkerBottom()); + assertEquals(INSERTION_MARKER_HORIZONTAL, info2.getInsertionMarkerHorizontal(), EPSILON); + assertEquals(INSERTION_MARKER_TOP, info2.getInsertionMarkerTop(), EPSILON); + assertEquals(INSERTION_MARKER_BASELINE, info2.getInsertionMarkerBaseline(), EPSILON); + assertEquals(INSERTION_MARKER_BOTOM, info2.getInsertionMarkerBottom(), EPSILON); assertEquals(TRANSFORM_MATRIX, info2.getMatrix()); for (int i = 0; i < MANY_BOUNDS.length; i++) { final RectF expectedBounds = MANY_BOUNDS[i]; @@ -161,10 +173,10 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { assertEquals(COMPOSING_TEXT_START, info3.getComposingTextStart()); assertTrue(TextUtils.equals(COMPOSING_TEXT, info3.getComposingText())); assertEquals(INSERTION_MARKER_FLAGS, info3.getInsertionMarkerFlags()); - assertEquals(INSERTION_MARKER_HORIZONTAL, info3.getInsertionMarkerHorizontal()); - assertEquals(INSERTION_MARKER_TOP, info3.getInsertionMarkerTop()); - assertEquals(INSERTION_MARKER_BASELINE, info3.getInsertionMarkerBaseline()); - assertEquals(INSERTION_MARKER_BOTOM, info3.getInsertionMarkerBottom()); + assertEquals(INSERTION_MARKER_HORIZONTAL, info3.getInsertionMarkerHorizontal(), EPSILON); + assertEquals(INSERTION_MARKER_TOP, info3.getInsertionMarkerTop(), EPSILON); + assertEquals(INSERTION_MARKER_BASELINE, info3.getInsertionMarkerBaseline(), EPSILON); + assertEquals(INSERTION_MARKER_BOTOM, info3.getInsertionMarkerBottom(), EPSILON); assertEquals(TRANSFORM_MATRIX, info3.getMatrix()); for (int i = 0; i < MANY_BOUNDS.length; i++) { final RectF expectedBounds = MANY_BOUNDS[i]; @@ -187,10 +199,10 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { assertEquals(-1, uninitializedInfo.getComposingTextStart()); assertNull(uninitializedInfo.getComposingText()); assertEquals(0, uninitializedInfo.getInsertionMarkerFlags()); - assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerHorizontal()); - assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerTop()); - assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBaseline()); - assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBottom()); + assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerHorizontal(), EPSILON); + assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerTop(), EPSILON); + assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBaseline(), EPSILON); + assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBottom(), EPSILON); assertEquals(Matrix.IDENTITY_MATRIX, uninitializedInfo.getMatrix()); } @@ -199,7 +211,7 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { assertFalse(Objects.equals(reference, actual)); } - @SmallTest + @Test public void testEquality() throws Exception { final Matrix MATRIX1 = new Matrix(); MATRIX1.setTranslate(10.0f, 20.0f); @@ -357,7 +369,7 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { INSERTION_MARKER_FLAGS2).build()); } - @SmallTest + @Test public void testMatrixIsCopied() throws Exception { final Matrix MATRIX1 = new Matrix(); MATRIX1.setTranslate(10.0f, 20.0f); @@ -385,7 +397,7 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { assertEquals(MATRIX2, secondInstance.getMatrix()); } - @SmallTest + @Test public void testMatrixIsRequired() throws Exception { final int SELECTION_START = 30; final int SELECTION_END = 40; @@ -434,7 +446,7 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { } } - @SmallTest + @Test public void testBuilderAddCharacterBounds() throws Exception { // A negative index should be rejected. try { diff --git a/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeArrayTest.java b/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeArrayTest.java index a339f61fbe4e..8df18480ed5a 100644 --- a/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeArrayTest.java +++ b/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeArrayTest.java @@ -16,16 +16,24 @@ package android.view.inputmethod; +import static org.junit.Assert.assertEquals; + import android.os.Parcel; -import android.test.InstrumentationTestCase; -import android.test.suitebuilder.annotation.SmallTest; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; + import java.util.ArrayList; -public class InputMethodSubtypeArrayTest extends InstrumentationTestCase { - @SmallTest - public void testInstanciate() throws Exception { +@SmallTest +@RunWith(AndroidJUnit4.class) +public class InputMethodSubtypeArrayTest { + + @Test + public void testInstantiate() throws Exception { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); subtypes.add(createDummySubtype(0, "en_US")); subtypes.add(createDummySubtype(1, "en_US")); diff --git a/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeTest.java b/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeTest.java index d203465577da..c76359ee39bc 100644 --- a/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeTest.java +++ b/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeTest.java @@ -16,15 +16,26 @@ package android.view.inputmethod; +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 android.os.Parcel; -import android.test.InstrumentationTestCase; -import android.test.suitebuilder.annotation.SmallTest; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; + import java.util.Locale; import java.util.Objects; -public class InputMethodSubtypeTest extends InstrumentationTestCase { +@SmallTest +@RunWith(AndroidJUnit4.class) +public class InputMethodSubtypeTest { public void verifyLocale(final String localeString) { // InputMethodSubtype#getLocale() returns exactly the same string that is passed to the @@ -48,7 +59,7 @@ public class InputMethodSubtypeTest extends InstrumentationTestCase { cloneViaParcel(cloneViaParcel(createDummySubtype(localeString))).hashCode()); } - @SmallTest + @Test public void testLocaleObj_locale() { final InputMethodSubtype usSubtype = createDummySubtype("en_US"); Locale localeObject = usSubtype.getLocaleObject(); @@ -59,7 +70,7 @@ public class InputMethodSubtypeTest extends InstrumentationTestCase { assertTrue(localeObject == usSubtype.getLocaleObject()); } - @SmallTest + @Test public void testLocaleObj_languageTag() { final InputMethodSubtype usSubtype = createDummySubtypeUsingLanguageTag("en-US"); Locale localeObject = usSubtype.getLocaleObject(); @@ -71,7 +82,7 @@ public class InputMethodSubtypeTest extends InstrumentationTestCase { assertTrue(localeObject == usSubtype.getLocaleObject()); } - @SmallTest + @Test public void testLocaleObj_emptyLocale() { final InputMethodSubtype emptyLocaleSubtype = createDummySubtype(""); assertNull(emptyLocaleSubtype.getLocaleObject()); @@ -80,7 +91,7 @@ public class InputMethodSubtypeTest extends InstrumentationTestCase { assertNull(emptyLocaleSubtype.getLocaleObject()); } - @SmallTest + @Test public void testLocaleString() throws Exception { // The locale string in InputMethodSubtype has accepted an arbitrary text actually, // regardless of the validity of the text as a locale string. @@ -95,7 +106,7 @@ public class InputMethodSubtypeTest extends InstrumentationTestCase { verifyLocale("fil_PH"); } - @SmallTest + @Test public void testDeprecatedLocaleString() throws Exception { // Make sure "iw" is not automatically replaced with "he". final InputMethodSubtype subtypeIw = createDummySubtype("iw"); diff --git a/core/tests/coretests/src/android/view/inputmethod/SparseRectFArrayTest.java b/core/tests/coretests/src/android/view/inputmethod/SparseRectFArrayTest.java index f9fa017281b6..8c96b588d08f 100644 --- a/core/tests/coretests/src/android/view/inputmethod/SparseRectFArrayTest.java +++ b/core/tests/coretests/src/android/view/inputmethod/SparseRectFArrayTest.java @@ -16,15 +16,25 @@ package android.view.inputmethod; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + import android.graphics.RectF; import android.os.Parcel; -import android.test.InstrumentationTestCase; -import android.test.suitebuilder.annotation.SmallTest; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; import android.view.inputmethod.SparseRectFArray.SparseRectFArrayBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; + import java.util.Objects; -public class SparseRectFArrayTest extends InstrumentationTestCase { +@SmallTest +@RunWith(AndroidJUnit4.class) +public class SparseRectFArrayTest { // A test data for {@link SparseRectFArray}. null represents the gap of indices. private static final RectF[] MANY_RECTS = new RectF[] { null, @@ -49,7 +59,7 @@ public class SparseRectFArrayTest extends InstrumentationTestCase { new RectF(118.0f, 218.0f, 318.0f, 418.0f), }; - @SmallTest + @Test public void testBuilder() throws Exception { final RectF TEMP_RECT = new RectF(10.0f, 20.0f, 30.0f, 40.0f); final int TEMP_FLAGS = 0x1234; @@ -128,7 +138,7 @@ public class SparseRectFArrayTest extends InstrumentationTestCase { assertNull(builder.build().get(0)); } - @SmallTest + @Test public void testEquality() throws Exception { // Empty array should be equal. assertEqualRects(new SparseRectFArrayBuilder().build(), @@ -225,7 +235,7 @@ public class SparseRectFArrayTest extends InstrumentationTestCase { .build()); } - @SmallTest + @Test public void testBuilderAppend() throws Exception { // Key should be appended in ascending order. try { diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java index 9061c4407685..13d6749cbc2c 100644 --- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java +++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java @@ -16,11 +16,15 @@ package com.android.internal.inputmethod; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import android.content.pm.ApplicationInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; -import android.test.InstrumentationTestCase; -import android.test.suitebuilder.annotation.SmallTest; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; @@ -28,11 +32,16 @@ import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ControllerImpl; import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem; +import org.junit.Test; +import org.junit.runner.RunWith; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; -public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTestCase { +@SmallTest +@RunWith(AndroidJUnit4.class) +public class InputMethodSubtypeSwitchingControllerTest { private static final String DUMMY_PACKAGE_NAME = "dummy package name"; private static final String DUMMY_IME_LABEL = "dummy ime label"; private static final String DUMMY_SETTING_ACTIVITY_NAME = ""; @@ -190,7 +199,7 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe controller.onUserActionLocked(subtypeListItem.mImi, subtype); } - @SmallTest + @Test public void testControllerImpl() throws Exception { final List<ImeSubtypeListItem> disabledItems = createDisabledImeSubtypes(); final ImeSubtypeListItem disabledIme_en_US = disabledItems.get(0); @@ -250,7 +259,7 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe disabledSubtypeUnawareIme, null, null); } - @SmallTest + @Test public void testControllerImplWithUserAction() throws Exception { final List<ImeSubtypeListItem> enabledItems = createEnabledImeSubtypes(); final ImeSubtypeListItem latinIme_en_US = enabledItems.get(0); @@ -331,7 +340,7 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe switchingUnawarelatinIme_en_UK, switchUnawareJapaneseIme_ja_JP); } - @SmallTest + @Test public void testImeSubtypeListItem() throws Exception { final List<ImeSubtypeListItem> items = new ArrayList<>(); addDummyImeSubtypeListItems(items, "LatinIme", "LatinIme", @@ -360,7 +369,7 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe assertFalse(item_EN_US.mIsSystemLocale); } - @SmallTest + @Test public void testImeSubtypeListComparator() throws Exception { { final List<ImeSubtypeListItem> items = Arrays.asList( diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java index d89dc637f5e0..33cd328a6d80 100644 --- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java +++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java @@ -16,6 +16,15 @@ package com.android.internal.inputmethod; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.in; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.core.Is.is; +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 android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.ResolveInfo; @@ -24,30 +33,31 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.os.LocaleList; import android.os.Parcel; -import android.test.InstrumentationTestCase; -import android.test.suitebuilder.annotation.SmallTest; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; import android.util.ArrayMap; import android.util.ArraySet; import android.view.inputmethod.InputMethodInfo; -import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; import android.view.inputmethod.InputMethodSubtype; +import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; + +import org.junit.Test; +import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Objects; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.isIn; -import static org.hamcrest.Matchers.not; - -public class InputMethodUtilsTest extends InstrumentationTestCase { +@SmallTest +@RunWith(AndroidJUnit4.class) +public class InputMethodUtilsTest { private static final boolean IS_AUX = true; private static final boolean IS_DEFAULT = true; private static final boolean IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE = true; private static final boolean IS_ASCII_CAPABLE = true; private static final boolean IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE = true; - private static final boolean IS_SYSTEM_READY = true; private static final Locale LOCALE_EN = new Locale("en"); private static final Locale LOCALE_EN_US = new Locale("en", "US"); private static final Locale LOCALE_EN_GB = new Locale("en", "GB"); @@ -77,7 +87,7 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { private static final String EXTRA_VALUE_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE = "EnabledWhenDefaultIsNotAsciiCapable"; - @SmallTest + @Test public void testVoiceImes() throws Exception { // locale: en_US assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_US, @@ -101,7 +111,7 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { "DummyNonDefaultAutoVoiceIme1"); } - @SmallTest + @Test public void testKeyboardImes() throws Exception { // locale: en_US assertDefaultEnabledImes(getSamplePreinstalledImes("en-rUS"), LOCALE_EN_US, @@ -136,7 +146,7 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { "com.android.apps.inputmethod.latin", "com.android.apps.inputmethod.voice"); } - @SmallTest + @Test public void testParcelable() throws Exception { final ArrayList<InputMethodInfo> originalList = getSamplePreinstalledImes("en-rUS"); final List<InputMethodInfo> clonedList = cloneViaParcel(originalList); @@ -153,7 +163,7 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { } } - @SmallTest + @Test public void testGetImplicitlyApplicableSubtypesLocked() throws Exception { final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, @@ -434,8 +444,8 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { InputMethodUtils.getImplicitlyApplicableSubtypesLocked( getResourcesForLocales(Locale.forLanguageTag("sr-Latn-RS")), imi); assertEquals(2, result.size()); - assertThat(nonAutoSrLatn, isIn(result)); - assertThat(nonAutoHandwritingSrLatn, isIn(result)); + assertThat(nonAutoSrLatn, is(in(result))); + assertThat(nonAutoHandwritingSrLatn, is(in(result))); } { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>(); @@ -454,8 +464,8 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { InputMethodUtils.getImplicitlyApplicableSubtypesLocked( getResourcesForLocales(Locale.forLanguageTag("sr-Cyrl-RS")), imi); assertEquals(2, result.size()); - assertThat(nonAutoSrCyrl, isIn(result)); - assertThat(nonAutoHandwritingSrCyrl, isIn(result)); + assertThat(nonAutoSrCyrl, is(in(result))); + assertThat(nonAutoHandwritingSrCyrl, is(in(result))); } // Make sure that secondary locales are taken into account to find the best matching @@ -486,12 +496,12 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { Locale.forLanguageTag("en-US")), imi); assertEquals(6, result.size()); - assertThat(nonAutoEnGB, isIn(result)); - assertThat(nonAutoFr, isIn(result)); - assertThat(nonAutoSrLatn, isIn(result)); - assertThat(nonAutoHandwritingEn, isIn(result)); - assertThat(nonAutoHandwritingFr, isIn(result)); - assertThat(nonAutoHandwritingSrLatn, isIn(result)); + assertThat(nonAutoEnGB, is(in(result))); + assertThat(nonAutoFr, is(in(result))); + assertThat(nonAutoSrLatn, is(in(result))); + assertThat(nonAutoHandwritingEn, is(in(result))); + assertThat(nonAutoHandwritingFr, is(in(result))); + assertThat(nonAutoHandwritingSrLatn, is(in(result))); } // Make sure that 3-letter language code can be handled. @@ -604,16 +614,16 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { final ArrayList<InputMethodSubtype> result = InputMethodUtils.getImplicitlyApplicableSubtypesLocked( getResourcesForLocales(LOCALE_FR, LOCALE_EN_US, LOCALE_JA_JP), imi); - assertThat(nonAutoFrCA, isIn(result)); - assertThat(nonAutoEnUS, isIn(result)); - assertThat(nonAutoJa, isIn(result)); - assertThat(nonAutoIn, not(isIn(result))); - assertThat(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype, not(isIn(result))); - assertThat(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype, not(isIn(result))); + assertThat(nonAutoFrCA, is(in(result))); + assertThat(nonAutoEnUS, is(in(result))); + assertThat(nonAutoJa, is(in(result))); + assertThat(nonAutoIn, not(is(in(result)))); + assertThat(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype, not(is(in(result)))); + assertThat(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype, not(is(in(result)))); } } - @SmallTest + @Test public void testContainsSubtypeOf() throws Exception { final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, @@ -788,7 +798,7 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { private Context createTargetContextWithLocales(final LocaleList locales) { final Configuration resourceConfiguration = new Configuration(); resourceConfiguration.setLocales(locales); - return getInstrumentation() + return InstrumentationRegistry.getInstrumentation() .getTargetContext() .createConfigurationContext(resourceConfiguration); } @@ -1043,7 +1053,7 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { return preinstalledImes; } - @SmallTest + @Test public void testGetSuitableLocalesForSpellChecker() throws Exception { { final ArrayList<Locale> locales = @@ -1138,7 +1148,7 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { } } - @SmallTest + @Test public void testParseInputMethodsAndSubtypesString() { // Trivial cases. { @@ -1264,7 +1274,7 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { } } - @SmallTest + @Test public void testbuildInputMethodsAndSubtypesString() { { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); @@ -1272,7 +1282,7 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); - map.put("ime0", new ArraySet<String>()); + map.put("ime0", new ArraySet<>()); assertEquals("ime0", InputMethodUtils.buildInputMethodsAndSubtypesString(map)); } { @@ -1300,8 +1310,8 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); - map.put("ime0", new ArraySet<String>()); - map.put("ime1", new ArraySet<String>()); + map.put("ime0", new ArraySet<>()); + map.put("ime1", new ArraySet<>()); ArraySet<String> validSequences = new ArraySet<>(); validSequences.add("ime0:ime1"); @@ -1314,7 +1324,7 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { ArraySet<String> subtypes1 = new ArraySet<>(); subtypes1.add("subtype0"); map.put("ime0", subtypes1); - map.put("ime1", new ArraySet<String>()); + map.put("ime1", new ArraySet<>()); ArraySet<String> validSequences = new ArraySet<>(); validSequences.add("ime0;subtype0:ime1"); @@ -1328,7 +1338,7 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { subtypes1.add("subtype0"); subtypes1.add("subtype1"); map.put("ime0", subtypes1); - map.put("ime1", new ArraySet<String>()); + map.put("ime1", new ArraySet<>()); ArraySet<String> validSequences = new ArraySet<>(); validSequences.add("ime0;subtype0;subtype1:ime1"); @@ -1380,7 +1390,7 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { } } - @SmallTest + @Test public void testConstructLocaleFromString() throws Exception { assertEquals(new Locale("en"), InputMethodUtils.constructLocaleFromString("en")); assertEquals(new Locale("en", "US"), InputMethodUtils.constructLocaleFromString("en_US")); diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java index cd339fb95509..549511a420eb 100644 --- a/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java +++ b/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java @@ -16,24 +16,25 @@ package com.android.internal.inputmethod; +import static org.junit.Assert.assertEquals; + import android.os.LocaleList; -import android.test.InstrumentationTestCase; -import android.test.suitebuilder.annotation.SmallTest; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.Locale; -public class LocaleUtilsTest extends InstrumentationTestCase { +@SmallTest +@RunWith(AndroidJUnit4.class) +public class LocaleUtilsTest { - private static final LocaleUtils.LocaleExtractor<Locale> sIdentityMapper = - new LocaleUtils.LocaleExtractor<Locale>() { - @Override - public Locale get(Locale source) { - return source; - } - }; + private static final LocaleUtils.LocaleExtractor<Locale> sIdentityMapper = source -> source; - @SmallTest + @Test public void testFilterByLanguageEmptyLanguageList() throws Exception { final ArrayList<Locale> availableLocales = new ArrayList<>(); availableLocales.add(Locale.forLanguageTag("en-US")); @@ -49,7 +50,7 @@ public class LocaleUtilsTest extends InstrumentationTestCase { assertEquals(0, dest.size()); } - @SmallTest + @Test public void testFilterDoesNotMatchAnything() throws Exception { final ArrayList<Locale> availableLocales = new ArrayList<>(); availableLocales.add(Locale.forLanguageTag("en-US")); @@ -65,7 +66,7 @@ public class LocaleUtilsTest extends InstrumentationTestCase { assertEquals(0, dest.size()); } - @SmallTest + @Test public void testFilterByLanguageEmptySource() throws Exception { final ArrayList<Locale> availableLocales = new ArrayList<>(); @@ -76,7 +77,7 @@ public class LocaleUtilsTest extends InstrumentationTestCase { assertEquals(0, dest.size()); } - @SmallTest + @Test public void testFilterByLanguageNullAvailableLocales() throws Exception { { final LocaleList preferredLocales = @@ -138,7 +139,7 @@ public class LocaleUtilsTest extends InstrumentationTestCase { } } - @SmallTest + @Test public void testFilterByLanguage() throws Exception { { final ArrayList<Locale> availableLocales = new ArrayList<>(); @@ -172,7 +173,7 @@ public class LocaleUtilsTest extends InstrumentationTestCase { } } - @SmallTest + @Test public void testFilterByLanguageTheSameLanguage() throws Exception { { final LocaleList preferredLocales = @@ -223,7 +224,7 @@ public class LocaleUtilsTest extends InstrumentationTestCase { } } - @SmallTest + @Test public void testFilterByLanguageFallbackRules() throws Exception { { final LocaleList preferredLocales = LocaleList.forLanguageTags("sr-Latn-RS"); @@ -355,6 +356,7 @@ public class LocaleUtilsTest extends InstrumentationTestCase { } } + @Test public void testFilterKnownLimitation() throws Exception { // Following test cases are not for intentional behavior but checks for preventing the // behavior from becoming worse. diff --git a/graphics/java/android/graphics/drawable/RippleComponent.java b/graphics/java/android/graphics/drawable/RippleComponent.java index 0e38826eb34b..626bcee9454b 100644 --- a/graphics/java/android/graphics/drawable/RippleComponent.java +++ b/graphics/java/android/graphics/drawable/RippleComponent.java @@ -93,12 +93,8 @@ abstract class RippleComponent { protected final void onHotspotBoundsChanged() { if (!mHasMaxRadius) { - final float halfWidth = mBounds.width() / 2.0f; - final float halfHeight = mBounds.height() / 2.0f; - final float targetRadius = (float) Math.sqrt(halfWidth * halfWidth - + halfHeight * halfHeight); - - onTargetRadiusChanged(targetRadius); + mTargetRadius = getTargetRadius(mBounds); + onTargetRadiusChanged(mTargetRadius); } } diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java index 8b185f2b8903..734cff542c51 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -299,6 +299,12 @@ public class RippleDrawable extends LayerDrawable { onHotspotBoundsChanged(); } + final int count = mExitingRipplesCount; + final RippleForeground[] ripples = mExitingRipples; + for (int i = 0; i < count; i++) { + ripples[i].onBoundsChange(); + } + if (mBackground != null) { mBackground.onBoundsChange(); } @@ -560,8 +566,7 @@ public class RippleDrawable extends LayerDrawable { y = mHotspotBounds.exactCenterY(); } - final boolean isBounded = isBounded(); - mRipple = new RippleForeground(this, mHotspotBounds, x, y, isBounded, mForceSoftware); + mRipple = new RippleForeground(this, mHotspotBounds, x, y, mForceSoftware); } mRipple.setup(mState.mMaxRadius, mDensity); diff --git a/graphics/java/android/graphics/drawable/RippleForeground.java b/graphics/java/android/graphics/drawable/RippleForeground.java index 0b5020cbe55c..ecbf5780d67f 100644 --- a/graphics/java/android/graphics/drawable/RippleForeground.java +++ b/graphics/java/android/graphics/drawable/RippleForeground.java @@ -30,6 +30,7 @@ import android.view.DisplayListCanvas; import android.view.RenderNodeAnimator; import android.view.animation.AnimationUtils; import android.view.animation.LinearInterpolator; +import android.view.animation.PathInterpolator; import java.util.ArrayList; @@ -38,18 +39,14 @@ import java.util.ArrayList; */ class RippleForeground extends RippleComponent { private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator(); - private static final TimeInterpolator DECELERATE_INTERPOLATOR = new LogDecelerateInterpolator( - 400f, 1.4f, 0); + // Matches R.interpolator.fast_out_slow_in but as we have no context we can't just import that + private static final TimeInterpolator DECELERATE_INTERPOLATOR = + new PathInterpolator(0.4f, 0f, 0.2f, 1f); - // Pixel-based accelerations and velocities. - private static final float WAVE_TOUCH_DOWN_ACCELERATION = 2048; - private static final float WAVE_OPACITY_DECAY_VELOCITY = 3; - - // Bounded ripple animation properties. - private static final int BOUNDED_ORIGIN_EXIT_DURATION = 300; - private static final int BOUNDED_RADIUS_EXIT_DURATION = 800; - private static final int BOUNDED_OPACITY_EXIT_DURATION = 400; - private static final float MAX_BOUNDED_RADIUS = 350; + // Time it takes for the ripple to expand + private static final int RIPPLE_ENTER_DURATION = 225; + // Time it takes for the ripple to slide from the touch to the center point + private static final int RIPPLE_ORIGIN_DURATION = 225; private static final int OPACITY_ENTER_DURATION = 75; private static final int OPACITY_EXIT_DURATION = 150; @@ -71,9 +68,6 @@ class RippleForeground extends RippleComponent { private float mTargetX = 0; private float mTargetY = 0; - /** Ripple target radius used when bounded. Not used for clamping. */ - private float mBoundedRadius = 0; - // Software rendering properties. private float mOpacity = 0; @@ -107,19 +101,13 @@ class RippleForeground extends RippleComponent { private float mStartRadius = 0; public RippleForeground(RippleDrawable owner, Rect bounds, float startingX, float startingY, - boolean isBounded, boolean forceSoftware) { + boolean forceSoftware) { super(owner, bounds); mForceSoftware = forceSoftware; mStartingX = startingX; mStartingY = startingY; - if (isBounded) { - mBoundedRadius = MAX_BOUNDED_RADIUS * 0.9f - + (float) (MAX_BOUNDED_RADIUS * Math.random() * 0.1); - } else { - mBoundedRadius = 0; - } // Take 60% of the maximum of the width and height, then divided half to get the radius. mStartRadius = Math.max(bounds.width(), bounds.height()) * 0.3f; } @@ -127,6 +115,7 @@ class RippleForeground extends RippleComponent { @Override protected void onTargetRadiusChanged(float targetRadius) { clampStartingPosition(); + switchToUiThreadAnimation(); } private void drawSoftware(Canvas c, Paint p) { @@ -228,16 +217,14 @@ class RippleForeground extends RippleComponent { } mRunningSwAnimators.clear(); - final int duration = getRadiusDuration(); - final ObjectAnimator tweenRadius = ObjectAnimator.ofFloat(this, TWEEN_RADIUS, 1); - tweenRadius.setDuration(duration); + tweenRadius.setDuration(RIPPLE_ENTER_DURATION); tweenRadius.setInterpolator(DECELERATE_INTERPOLATOR); tweenRadius.start(); mRunningSwAnimators.add(tweenRadius); final ObjectAnimator tweenOrigin = ObjectAnimator.ofFloat(this, TWEEN_ORIGIN, 1); - tweenOrigin.setDuration(duration); + tweenOrigin.setDuration(RIPPLE_ORIGIN_DURATION); tweenOrigin.setInterpolator(DECELERATE_INTERPOLATOR); tweenOrigin.start(); mRunningSwAnimators.add(tweenOrigin); @@ -267,20 +254,18 @@ class RippleForeground extends RippleComponent { final Paint paint = mOwner.getRipplePaint(); mPropPaint = CanvasProperty.createPaint(paint); - final int radiusDuration = getRadiusDuration(); - final RenderNodeAnimator radius = new RenderNodeAnimator(mPropRadius, mTargetRadius); - radius.setDuration(radiusDuration); + radius.setDuration(RIPPLE_ORIGIN_DURATION); radius.setInterpolator(DECELERATE_INTERPOLATOR); mPendingHwAnimators.add(radius); final RenderNodeAnimator x = new RenderNodeAnimator(mPropX, mTargetX); - x.setDuration(radiusDuration); + x.setDuration(RIPPLE_ORIGIN_DURATION); x.setInterpolator(DECELERATE_INTERPOLATOR); mPendingHwAnimators.add(x); final RenderNodeAnimator y = new RenderNodeAnimator(mPropY, mTargetY); - y.setDuration(radiusDuration); + y.setDuration(RIPPLE_ORIGIN_DURATION); y.setInterpolator(DECELERATE_INTERPOLATOR); mPendingHwAnimators.add(y); @@ -333,12 +318,6 @@ class RippleForeground extends RippleComponent { return MathUtils.lerp(mClampedStartingY - mBounds.exactCenterY(), mTargetY, mTweenY); } - private int getRadiusDuration() { - final float remainingRadius = mTargetRadius - getCurrentRadius(); - return (int) (1000 * Math.sqrt(remainingRadius / WAVE_TOUCH_DOWN_ACCELERATION * - mDensityScale) + 0.5); - } - private float getCurrentRadius() { return MathUtils.lerp(mStartRadius, mTargetRadius, mTweenRadius); } @@ -402,6 +381,14 @@ class RippleForeground extends RippleComponent { } } + private void clearHwProps() { + mPropPaint = null; + mPropRadius = null; + mPropX = null; + mPropY = null; + mUsingProperties = false; + } + private final AnimatorListenerAdapter mAnimationListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animator) { @@ -410,39 +397,20 @@ class RippleForeground extends RippleComponent { pruneSwFinished(); if (mRunningHwAnimators.isEmpty()) { - mPropPaint = null; - mPropRadius = null; - mPropX = null; - mPropY = null; + clearHwProps(); } } }; - /** - * Interpolator with a smooth log deceleration. - */ - private static final class LogDecelerateInterpolator implements TimeInterpolator { - private final float mBase; - private final float mDrift; - private final float mTimeScale; - private final float mOutputScale; - - public LogDecelerateInterpolator(float base, float timeScale, float drift) { - mBase = base; - mDrift = drift; - mTimeScale = 1f / timeScale; - - mOutputScale = 1f / computeLog(1f); - } - - private float computeLog(float t) { - return 1f - (float) Math.pow(mBase, -t * mTimeScale) + (mDrift * t); - } - - @Override - public float getInterpolation(float t) { - return computeLog(t) * mOutputScale; + private void switchToUiThreadAnimation() { + for (int i = 0; i < mRunningHwAnimators.size(); i++) { + Animator animator = mRunningHwAnimators.get(i); + animator.removeListener(mAnimationListener); + animator.end(); } + mRunningHwAnimators.clear(); + clearHwProps(); + invalidateSelf(); } /** diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java index d6b1cf1da8a2..a250d1f01ba1 100644 --- a/keystore/java/android/security/keystore/KeyProperties.java +++ b/keystore/java/android/security/keystore/KeyProperties.java @@ -39,13 +39,12 @@ public abstract class KeyProperties { * @hide */ @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = true, - value = { - PURPOSE_ENCRYPT, - PURPOSE_DECRYPT, - PURPOSE_SIGN, - PURPOSE_VERIFY, - }) + @IntDef(flag = true, prefix = { "PURPOSE_" }, value = { + PURPOSE_ENCRYPT, + PURPOSE_DECRYPT, + PURPOSE_SIGN, + PURPOSE_VERIFY, + }) public @interface PurposeEnum {} /** @@ -126,7 +125,7 @@ public abstract class KeyProperties { * @hide */ @Retention(RetentionPolicy.SOURCE) - @StringDef({ + @StringDef(prefix = { "KEY_" }, value = { KEY_ALGORITHM_RSA, KEY_ALGORITHM_EC, KEY_ALGORITHM_AES, @@ -267,7 +266,7 @@ public abstract class KeyProperties { * @hide */ @Retention(RetentionPolicy.SOURCE) - @StringDef({ + @StringDef(prefix = { "BLOCK_MODE_" }, value = { BLOCK_MODE_ECB, BLOCK_MODE_CBC, BLOCK_MODE_CTR, @@ -354,7 +353,7 @@ public abstract class KeyProperties { * @hide */ @Retention(RetentionPolicy.SOURCE) - @StringDef({ + @StringDef(prefix = { "ENCRYPTION_PADDING_" }, value = { ENCRYPTION_PADDING_NONE, ENCRYPTION_PADDING_PKCS7, ENCRYPTION_PADDING_RSA_PKCS1, @@ -437,7 +436,7 @@ public abstract class KeyProperties { * @hide */ @Retention(RetentionPolicy.SOURCE) - @StringDef({ + @StringDef(prefix = { "SIGNATURE_PADDING_" }, value = { SIGNATURE_PADDING_RSA_PKCS1, SIGNATURE_PADDING_RSA_PSS, }) @@ -497,7 +496,7 @@ public abstract class KeyProperties { * @hide */ @Retention(RetentionPolicy.SOURCE) - @StringDef({ + @StringDef(prefix = { "DIGEST_" }, value = { DIGEST_NONE, DIGEST_MD5, DIGEST_SHA1, @@ -647,11 +646,12 @@ public abstract class KeyProperties { * @hide */ @Retention(RetentionPolicy.SOURCE) - @IntDef({ - ORIGIN_GENERATED, - ORIGIN_IMPORTED, - ORIGIN_UNKNOWN, - }) + @IntDef(prefix = { "ORIGIN_" }, value = { + ORIGIN_GENERATED, + ORIGIN_IMPORTED, + ORIGIN_UNKNOWN, + }) + public @interface OriginEnum {} /** Key was generated inside AndroidKeyStore. */ diff --git a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java index b15e0a221c6f..7cb8e375a969 100644 --- a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java @@ -81,12 +81,16 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable { } out.writeByteArray(mSpec.getCertificateSubject().getEncoded()); out.writeByteArray(mSpec.getCertificateSerialNumber().toByteArray()); - writeOptionalDate(out, mSpec.getCertificateNotBefore()); - writeOptionalDate(out, mSpec.getCertificateNotAfter()); + out.writeLong(mSpec.getCertificateNotBefore().getTime()); + out.writeLong(mSpec.getCertificateNotAfter().getTime()); writeOptionalDate(out, mSpec.getKeyValidityStart()); writeOptionalDate(out, mSpec.getKeyValidityForOriginationEnd()); writeOptionalDate(out, mSpec.getKeyValidityForConsumptionEnd()); - out.writeStringArray(mSpec.getDigests()); + if (mSpec.isDigestsSpecified()) { + out.writeStringArray(mSpec.getDigests()); + } else { + out.writeStringArray(null); + } out.writeStringArray(mSpec.getEncryptionPaddings()); out.writeStringArray(mSpec.getSignaturePaddings()); out.writeStringArray(mSpec.getBlockModes()); @@ -111,9 +115,15 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable { private ParcelableKeyGenParameterSpec(Parcel in) { String keystoreAlias = in.readString(); int purposes = in.readInt(); - KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(keystoreAlias, purposes); + KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder( + keystoreAlias, purposes); builder.setUid(in.readInt()); - builder.setKeySize(in.readInt()); + // KeySize is -1 by default, if the KeyGenParameterSpec previously parcelled had the default + // value, do not set it as this will cause setKeySize to throw. + int keySize = in.readInt(); + if (keySize >= 0) { + builder.setKeySize(keySize); + } int keySpecType = in.readInt(); AlgorithmParameterSpec algorithmSpec = null; @@ -128,17 +138,22 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable { algorithmSpec = new ECGenParameterSpec(stdName); } else { throw new IllegalArgumentException( - String.format("Unknown algorithm parameter spec: %d", algorithmSpec)); + String.format("Unknown algorithm parameter spec: %d", keySpecType)); + } + if (algorithmSpec != null) { + builder.setAlgorithmParameterSpec(algorithmSpec); } - builder.setAlgorithmParameterSpec(algorithmSpec); builder.setCertificateSubject(new X500Principal(in.createByteArray())); builder.setCertificateSerialNumber(new BigInteger(in.createByteArray())); - builder.setCertificateNotBefore(readDateOrNull(in)); - builder.setCertificateNotAfter(readDateOrNull(in)); + builder.setCertificateNotBefore(new Date(in.readLong())); + builder.setCertificateNotAfter(new Date(in.readLong())); builder.setKeyValidityStart(readDateOrNull(in)); builder.setKeyValidityForOriginationEnd(readDateOrNull(in)); builder.setKeyValidityForConsumptionEnd(readDateOrNull(in)); - builder.setDigests(in.createStringArray()); + String[] digests = in.createStringArray(); + if (digests != null) { + builder.setDigests(digests); + } builder.setEncryptionPaddings(in.createStringArray()); builder.setSignaturePaddings(in.createStringArray()); builder.setBlockModes(in.createStringArray()); diff --git a/libs/hwui/NinePatchUtils.h b/libs/hwui/NinePatchUtils.h index 8f866f50e450..db9509fff378 100644 --- a/libs/hwui/NinePatchUtils.h +++ b/libs/hwui/NinePatchUtils.h @@ -53,10 +53,13 @@ static inline int NumDistinctRects(const SkCanvas::Lattice& lattice) { return xRects * yRects; } -static inline void SetLatticeFlags(SkCanvas::Lattice* lattice, SkCanvas::Lattice::Flags* flags, - int numFlags, const Res_png_9patch& chunk) { - lattice->fFlags = flags; - sk_bzero(flags, numFlags * sizeof(SkCanvas::Lattice::Flags)); +static inline void SetLatticeFlags(SkCanvas::Lattice* lattice, + SkCanvas::Lattice::RectType* flags, int numFlags, const Res_png_9patch& chunk, + SkColor* colors) { + lattice->fRectTypes = flags; + lattice->fColors = colors; + sk_bzero(flags, numFlags * sizeof(SkCanvas::Lattice::RectType)); + sk_bzero(colors, numFlags * sizeof(SkColor)); bool needPadRow = lattice->fYCount > 0 && 0 == lattice->fYDivs[0]; bool needPadCol = lattice->fXCount > 0 && 0 == lattice->fXDivs[0]; @@ -65,6 +68,7 @@ static inline void SetLatticeFlags(SkCanvas::Lattice* lattice, SkCanvas::Lattice if (needPadRow) { // Skip flags for the degenerate first row of rects. flags += lattice->fXCount + 1; + colors += lattice->fXCount + 1; yCount--; } @@ -75,20 +79,28 @@ static inline void SetLatticeFlags(SkCanvas::Lattice* lattice, SkCanvas::Lattice if (0 == x && needPadCol) { // First rect of each column is degenerate, skip the flag. flags++; + colors++; continue; } - if (0 == chunk.getColors()[i++]) { - *flags = SkCanvas::Lattice::kTransparent_Flags; + uint32_t currentColor = chunk.getColors()[i++]; + if (Res_png_9patch::TRANSPARENT_COLOR == currentColor) { + *flags = SkCanvas::Lattice::kTransparent; + setFlags = true; + } else if (Res_png_9patch::NO_COLOR != currentColor) { + *flags = SkCanvas::Lattice::kFixedColor; + *colors = currentColor; setFlags = true; } flags++; + colors++; } } if (!setFlags) { - lattice->fFlags = nullptr; + lattice->fRectTypes = nullptr; + lattice->fColors = nullptr; } } diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index eb0d161d71d1..13e1ebec943e 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -699,7 +699,8 @@ void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, floa SkCanvas::Lattice lattice; NinePatchUtils::SetLatticeDivs(&lattice, chunk, bitmap.width(), bitmap.height()); - lattice.fFlags = nullptr; + lattice.fRectTypes = nullptr; + lattice.fColors = nullptr; int numFlags = 0; if (chunk.numColors > 0 && chunk.numColors == NinePatchUtils::NumDistinctRects(lattice)) { // We can expect the framework to give us a color for every distinct rect. @@ -707,9 +708,10 @@ void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, floa numFlags = (lattice.fXCount + 1) * (lattice.fYCount + 1); } - SkAutoSTMalloc<25, SkCanvas::Lattice::Flags> flags(numFlags); + SkAutoSTMalloc<25, SkCanvas::Lattice::RectType> flags(numFlags); + SkAutoSTMalloc<25, SkColor> colors(numFlags); if (numFlags > 0) { - NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk); + NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk, colors.get()); } lattice.fBounds = nullptr; diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp index 288d0395370c..107890e57a19 100644 --- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp +++ b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp @@ -45,8 +45,7 @@ CopyResult SkiaOpenGLReadback::copyImageInto(EGLImageKHR eglImage, const Matrix4 if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface()); LOG_ALWAYS_FATAL_IF(!glInterface.get()); - grContext.reset(GrContext::Create(GrBackend::kOpenGL_GrBackend, - (GrBackendContext)glInterface.get())); + grContext = GrContext::MakeGL(std::move(glInterface)); } else { grContext->resetContext(); } diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index 91b35c281b04..035cea3f61b0 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -218,7 +218,8 @@ void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& ch SkCanvas::Lattice lattice; NinePatchUtils::SetLatticeDivs(&lattice, chunk, bitmap.width(), bitmap.height()); - lattice.fFlags = nullptr; + lattice.fRectTypes = nullptr; + lattice.fColors = nullptr; int numFlags = 0; if (chunk.numColors > 0 && chunk.numColors == NinePatchUtils::NumDistinctRects(lattice)) { // We can expect the framework to give us a color for every distinct rect. @@ -226,9 +227,10 @@ void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& ch numFlags = (lattice.fXCount + 1) * (lattice.fYCount + 1); } - SkAutoSTMalloc<25, SkCanvas::Lattice::Flags> flags(numFlags); + SkAutoSTMalloc<25, SkCanvas::Lattice::RectType> flags(numFlags); + SkAutoSTMalloc<25, SkColor> colors(numFlags); if (numFlags > 0) { - NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk); + NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk, colors.get()); } lattice.fBounds = nullptr; diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp index 5e89faec1bab..907f2d2d398f 100644 --- a/libs/hwui/renderthread/CacheManager.cpp +++ b/libs/hwui/renderthread/CacheManager.cpp @@ -53,13 +53,13 @@ CacheManager::CacheManager(const DisplayInfo& display) : mMaxSurfaceArea(display } } -void CacheManager::reset(GrContext* context) { - if (context != mGrContext.get()) { +void CacheManager::reset(sk_sp<GrContext> context) { + if (context != mGrContext) { destroy(); } if (context) { - mGrContext = sk_ref_sp(context); + mGrContext = std::move(context); mGrContext->getResourceCacheLimits(&mMaxResources, nullptr); updateContextCacheSizes(); } diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h index d0370453c258..7d733525194f 100644 --- a/libs/hwui/renderthread/CacheManager.h +++ b/libs/hwui/renderthread/CacheManager.h @@ -61,7 +61,7 @@ private: CacheManager(const DisplayInfo& display); - void reset(GrContext* grContext); + void reset(sk_sp<GrContext> grContext); void destroy(); void updateContextCacheSizes(); diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp index 4df7cafa4792..5b87e1013baf 100644 --- a/libs/hwui/renderthread/EglManager.cpp +++ b/libs/hwui/renderthread/EglManager.cpp @@ -141,8 +141,9 @@ void EglManager::initialize() { GrContextOptions options; options.fDisableDistanceFieldPaths = true; mRenderThread.cacheManager().configureContext(&options); - mRenderThread.setGrContext(GrContext::Create(GrBackend::kOpenGL_GrBackend, - (GrBackendContext)glInterface.get(), options)); + sk_sp<GrContext> grContext(GrContext::MakeGL(std::move(glInterface), options)); + LOG_ALWAYS_FATAL_IF(!grContext.get()); + mRenderThread.setGrContext(grContext); } } @@ -238,9 +239,9 @@ void EglManager::loadConfigs() { if (!eglChooseConfig(mEglDisplay, attribs16F, &mEglConfigWideGamut, numConfigs, &numConfigs) || numConfigs != 1) { - LOG_ALWAYS_FATAL( - "Device claims wide gamut support, cannot find matching config, error = %s", + ALOGE("Device claims wide gamut support, cannot find matching config, error = %s", eglErrorString()); + EglExtensions.pixelFormatFloat = false; } } } diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 20443ec38c90..79dc09ffbf1d 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -173,12 +173,12 @@ Readback& RenderThread::readback() { return *mReadback; } -void RenderThread::setGrContext(GrContext* context) { +void RenderThread::setGrContext(sk_sp<GrContext> context) { mCacheManager->reset(context); - if (mGrContext.get()) { + if (mGrContext) { mGrContext->releaseResourcesAndAbandonContext(); } - mGrContext.reset(context); + mGrContext = std::move(context); } int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) { diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h index 970537b69fad..3aa548773b3b 100644 --- a/libs/hwui/renderthread/RenderThread.h +++ b/libs/hwui/renderthread/RenderThread.h @@ -88,7 +88,7 @@ public: const DisplayInfo& mainDisplayInfo() { return mDisplayInfo; } GrContext* getGrContext() const { return mGrContext.get(); } - void setGrContext(GrContext* cxt); + void setGrContext(sk_sp<GrContext> cxt); CacheManager& cacheManager() { return *mCacheManager; } VulkanManager& vulkanManager() { return *mVkManager; } diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index a693e68afd66..9d246ffc9a4a 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -58,6 +58,7 @@ void VulkanManager::initialize() { mBackendContext.reset(GrVkBackendContext::Create(vkGetInstanceProcAddr, vkGetDeviceProcAddr, &mPresentQueueIndex, canPresent)); + LOG_ALWAYS_FATAL_IF(!mBackendContext.get()); // Get all the addresses of needed vulkan functions VkInstance instance = mBackendContext->fInstance; @@ -110,8 +111,9 @@ void VulkanManager::initialize() { GrContextOptions options; options.fDisableDistanceFieldPaths = true; mRenderThread.cacheManager().configureContext(&options); - mRenderThread.setGrContext( - GrContext::Create(kVulkan_GrBackend, (GrBackendContext)mBackendContext.get(), options)); + sk_sp<GrContext> grContext(GrContext::MakeVulkan(mBackendContext, options)); + LOG_ALWAYS_FATAL_IF(!grContext.get()); + mRenderThread.setGrContext(grContext); DeviceInfo::initialize(mRenderThread.getGrContext()->caps()->maxRenderTargetSize()); if (Properties::enablePartialUpdates && Properties::useBufferAge) { diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp index 3ac1a454bf28..e0303a8a62d5 100644 --- a/libs/hwui/service/GraphicsStatsService.cpp +++ b/libs/hwui/service/GraphicsStatsService.cpp @@ -42,7 +42,7 @@ static_assert(sizeof(sCurrentFileVersion) == sHeaderSize, "Header size is wrong" constexpr int sHistogramSize = ProfileData::HistogramSize(); static bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, - const std::string& package, int versionCode, + const std::string& package, int64_t versionCode, int64_t startTime, int64_t endTime, const ProfileData* data); static void dumpAsTextToFd(service::GraphicsStatsProto* proto, int outFd); @@ -154,7 +154,7 @@ bool GraphicsStatsService::parseFromFile(const std::string& path, } bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::string& package, - int versionCode, int64_t startTime, int64_t endTime, + int64_t versionCode, int64_t startTime, int64_t endTime, const ProfileData* data) { if (proto->stats_start() == 0 || proto->stats_start() > startTime) { proto->set_stats_start(startTime); @@ -230,7 +230,7 @@ void dumpAsTextToFd(service::GraphicsStatsProto* proto, int fd) { return; } dprintf(fd, "\nPackage: %s", proto->package_name().c_str()); - dprintf(fd, "\nVersion: %d", proto->version_code()); + dprintf(fd, "\nVersion: %lld", proto->version_code()); dprintf(fd, "\nStats since: %lldns", proto->stats_start()); dprintf(fd, "\nStats end: %lldns", proto->stats_end()); auto summary = proto->summary(); @@ -254,7 +254,7 @@ void dumpAsTextToFd(service::GraphicsStatsProto* proto, int fd) { } void GraphicsStatsService::saveBuffer(const std::string& path, const std::string& package, - int versionCode, int64_t startTime, int64_t endTime, + int64_t versionCode, int64_t startTime, int64_t endTime, const ProfileData* data) { service::GraphicsStatsProto statsProto; if (!parseFromFile(path, &statsProto)) { @@ -320,8 +320,8 @@ GraphicsStatsService::Dump* GraphicsStatsService::createDump(int outFd, DumpType } void GraphicsStatsService::addToDump(Dump* dump, const std::string& path, - const std::string& package, int versionCode, int64_t startTime, - int64_t endTime, const ProfileData* data) { + const std::string& package, int64_t versionCode, + int64_t startTime, int64_t endTime, const ProfileData* data) { service::GraphicsStatsProto statsProto; if (!path.empty() && !parseFromFile(path, &statsProto)) { statsProto.Clear(); diff --git a/libs/hwui/service/GraphicsStatsService.h b/libs/hwui/service/GraphicsStatsService.h index 7ddc219463f8..bce0f3ddbb82 100644 --- a/libs/hwui/service/GraphicsStatsService.h +++ b/libs/hwui/service/GraphicsStatsService.h @@ -44,12 +44,12 @@ public: }; ANDROID_API static void saveBuffer(const std::string& path, const std::string& package, - int versionCode, int64_t startTime, int64_t endTime, + int64_t versionCode, int64_t startTime, int64_t endTime, const ProfileData* data); ANDROID_API static Dump* createDump(int outFd, DumpType type); ANDROID_API static void addToDump(Dump* dump, const std::string& path, - const std::string& package, int versionCode, + const std::string& package, int64_t versionCode, int64_t startTime, int64_t endTime, const ProfileData* data); ANDROID_API static void addToDump(Dump* dump, const std::string& path); ANDROID_API static void finishDump(Dump* dump); diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java index 1b89c96602d3..19d467a69c29 100644 --- a/media/java/android/media/AudioDeviceInfo.java +++ b/media/java/android/media/AudioDeviceInfo.java @@ -127,6 +127,14 @@ public final class AudioDeviceInfo { } /** + * @hide + * @return The underlying {@link AudioDevicePort} instance. + */ + public AudioDevicePort getPort() { + return mPort; + } + + /** * @return The internal device ID. */ public int getId() { diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java index 12e5744d2035..e2f9b47ed482 100644 --- a/media/java/android/media/MediaDrm.java +++ b/media/java/android/media/MediaDrm.java @@ -977,7 +977,7 @@ public final class MediaDrm { public static final String PROPERTY_ALGORITHMS = "algorithms"; /** @hide */ - @StringDef({ + @StringDef(prefix = { "PROPERTY_" }, value = { PROPERTY_VENDOR, PROPERTY_VERSION, PROPERTY_DESCRIPTION, @@ -1010,7 +1010,7 @@ public final class MediaDrm { public static final String PROPERTY_DEVICE_UNIQUE_ID = "deviceUniqueId"; /** @hide */ - @StringDef({ + @StringDef(prefix = { "PROPERTY_" }, value = { PROPERTY_DEVICE_UNIQUE_ID, }) @Retention(RetentionPolicy.SOURCE) diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java index 31eb948dcd09..94d4d55639dc 100644 --- a/media/java/android/media/MediaMetadata.java +++ b/media/java/android/media/MediaMetadata.java @@ -45,34 +45,61 @@ public final class MediaMetadata implements Parcelable { /** * @hide */ - @StringDef({METADATA_KEY_TITLE, METADATA_KEY_ARTIST, METADATA_KEY_ALBUM, METADATA_KEY_AUTHOR, - METADATA_KEY_WRITER, METADATA_KEY_COMPOSER, METADATA_KEY_COMPILATION, - METADATA_KEY_DATE, METADATA_KEY_GENRE, METADATA_KEY_ALBUM_ARTIST, METADATA_KEY_ART_URI, - METADATA_KEY_ALBUM_ART_URI, METADATA_KEY_DISPLAY_TITLE, METADATA_KEY_DISPLAY_SUBTITLE, - METADATA_KEY_DISPLAY_DESCRIPTION, METADATA_KEY_DISPLAY_ICON_URI, - METADATA_KEY_MEDIA_ID, METADATA_KEY_MEDIA_URI}) + @StringDef(prefix = { "METADATA_KEY_" }, value = { + METADATA_KEY_TITLE, + METADATA_KEY_ARTIST, + METADATA_KEY_ALBUM, + METADATA_KEY_AUTHOR, + METADATA_KEY_WRITER, + METADATA_KEY_COMPOSER, + METADATA_KEY_COMPILATION, + METADATA_KEY_DATE, + METADATA_KEY_GENRE, + METADATA_KEY_ALBUM_ARTIST, + METADATA_KEY_ART_URI, + METADATA_KEY_ALBUM_ART_URI, + METADATA_KEY_DISPLAY_TITLE, + METADATA_KEY_DISPLAY_SUBTITLE, + METADATA_KEY_DISPLAY_DESCRIPTION, + METADATA_KEY_DISPLAY_ICON_URI, + METADATA_KEY_MEDIA_ID, + METADATA_KEY_MEDIA_URI, + }) @Retention(RetentionPolicy.SOURCE) public @interface TextKey {} /** * @hide */ - @StringDef({METADATA_KEY_DURATION, METADATA_KEY_YEAR, METADATA_KEY_TRACK_NUMBER, - METADATA_KEY_NUM_TRACKS, METADATA_KEY_DISC_NUMBER, METADATA_KEY_BT_FOLDER_TYPE}) + @StringDef(prefix = { "METADATA_KEY_" }, value = { + METADATA_KEY_DURATION, + METADATA_KEY_YEAR, + METADATA_KEY_TRACK_NUMBER, + METADATA_KEY_NUM_TRACKS, + METADATA_KEY_DISC_NUMBER, + METADATA_KEY_BT_FOLDER_TYPE, + }) @Retention(RetentionPolicy.SOURCE) public @interface LongKey {} /** * @hide */ - @StringDef({METADATA_KEY_ART, METADATA_KEY_ALBUM_ART, METADATA_KEY_DISPLAY_ICON}) + @StringDef(prefix = { "METADATA_KEY_" }, value = { + METADATA_KEY_ART, + METADATA_KEY_ALBUM_ART, + METADATA_KEY_DISPLAY_ICON, + }) @Retention(RetentionPolicy.SOURCE) public @interface BitmapKey {} /** * @hide */ - @StringDef({METADATA_KEY_USER_RATING, METADATA_KEY_RATING}) + @StringDef(prefix = { "METADATA_KEY_" }, value = { + METADATA_KEY_USER_RATING, + METADATA_KEY_RATING, + }) @Retention(RetentionPolicy.SOURCE) public @interface RatingKey {} diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java index 0f4609603eab..3bbc2c4e2304 100644 --- a/media/java/android/media/tv/TvContract.java +++ b/media/java/android/media/tv/TvContract.java @@ -1650,7 +1650,7 @@ public final class TvContract { public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/channel"; /** @hide */ - @StringDef({ + @StringDef(prefix = { "TYPE_" }, value = { TYPE_OTHER, TYPE_NTSC, TYPE_PAL, @@ -1863,7 +1863,7 @@ public final class TvContract { public static final String TYPE_PREVIEW = "TYPE_PREVIEW"; /** @hide */ - @StringDef({ + @StringDef(prefix = { "SERVICE_TYPE_" }, value = { SERVICE_TYPE_OTHER, SERVICE_TYPE_AUDIO_VIDEO, SERVICE_TYPE_AUDIO, @@ -1881,7 +1881,7 @@ public final class TvContract { public static final String SERVICE_TYPE_AUDIO = "SERVICE_TYPE_AUDIO"; /** @hide */ - @StringDef({ + @StringDef(prefix = { "VIDEO_FORMAT_" }, value = { VIDEO_FORMAT_240P, VIDEO_FORMAT_360P, VIDEO_FORMAT_480I, @@ -1930,7 +1930,7 @@ public final class TvContract { public static final String VIDEO_FORMAT_4320P = "VIDEO_FORMAT_4320P"; /** @hide */ - @StringDef({ + @StringDef(prefix = { "VIDEO_RESOLUTION_" }, value = { VIDEO_RESOLUTION_SD, VIDEO_RESOLUTION_ED, VIDEO_RESOLUTION_HD, diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp index 21410eac3d8d..b4ca88cd2bcf 100644 --- a/media/jni/soundpool/SoundPool.cpp +++ b/media/jni/soundpool/SoundPool.cpp @@ -24,7 +24,6 @@ #define USE_SHARED_MEM_BUFFER #include <media/AudioTrack.h> -#include <media/mediaplayer.h> #include "SoundPool.h" #include "SoundPoolThread.h" #include <media/AudioPolicyHelper.h> diff --git a/packages/PrintSpooler/res/values-pt-rPT/strings.xml b/packages/PrintSpooler/res/values-pt-rPT/strings.xml index eac6d36164da..5da31bde591a 100644 --- a/packages/PrintSpooler/res/values-pt-rPT/strings.xml +++ b/packages/PrintSpooler/res/values-pt-rPT/strings.xml @@ -56,8 +56,8 @@ <string name="print_select_printer" msgid="7388760939873368698">"Selecionar impressora"</string> <string name="print_forget_printer" msgid="5035287497291910766">"Esquecer impressora"</string> <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868"> - <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> impressora encontrada</item> <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> impressoras encontradas</item> + <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> impressora encontrada</item> </plurals> <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string> <string name="printer_info_desc" msgid="7181988788991581654">"Mais informações acerca desta impressora"</string> @@ -76,8 +76,8 @@ <string name="disabled_services_title" msgid="7313253167968363211">"Serviços desativados"</string> <string name="all_services_title" msgid="5578662754874906455">"Todos os serviços"</string> <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138"> - <item quantity="one">Instale para detetar <xliff:g id="COUNT_0">%1$s</xliff:g> impressora</item> <item quantity="other">Instale para detetar <xliff:g id="COUNT_1">%1$s</xliff:g> impressoras</item> + <item quantity="one">Instale para detetar <xliff:g id="COUNT_0">%1$s</xliff:g> impressora</item> </plurals> <string name="printing_notification_title_template" msgid="295903957762447362">"A imprimir <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string> <string name="cancelling_notification_title_template" msgid="1821759594704703197">"A cancelar <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string> diff --git a/packages/SettingsLib/Android.mk b/packages/SettingsLib/Android.mk index 894a1ab416da..69287e858532 100644 --- a/packages/SettingsLib/Android.mk +++ b/packages/SettingsLib/Android.mk @@ -19,8 +19,6 @@ LOCAL_SHARED_ANDROID_LIBRARIES := \ LOCAL_SHARED_JAVA_LIBRARIES := \ apptoolkit-lifecycle-common -LOCAL_STATIC_JAVA_LIBRARY := legacy-android-test - LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res LOCAL_JAR_EXCLUDE_FILES := none diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index 75a0a4238747..a5c2e41164a3 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -33,15 +33,13 @@ <string name="wifi_check_password_try_again" msgid="516958988102584767">"পাসওয়ার্ড দেখে আবার চেষ্টা করুন"</string> <string name="wifi_not_in_range" msgid="1136191511238508967">"পরিসরের মধ্যে নয়"</string> <string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"স্বয়ংক্রিয়ভাবে সংযোগ করবে না"</string> - <!-- no translation found for wifi_no_internet (4663834955626848401) --> - <skip /> + <string name="wifi_no_internet" msgid="4663834955626848401">"ইন্টারনেট অ্যাক্সেস নেই"</string> <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> দ্বারা সেভ করা"</string> <string name="connected_via_network_scorer" msgid="5713793306870815341">"স্বয়ংক্রিয়ভাবে %1$s এর মাধ্যমে সংযুক্ত হয়েছে"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"নেটওয়ার্কের রেটিং প্রদানকারীর মাধ্যমে স্বয়ংক্রিয়ভাবে সংযুক্ত"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s মাধ্যমে সংযুক্ত হয়েছে"</string> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s এর মাধ্যমে উপলব্ধ"</string> - <!-- no translation found for wifi_connected_no_internet (8202906332837777829) --> - <skip /> + <string name="wifi_connected_no_internet" msgid="8202906332837777829">"সংযুক্ত, ইন্টারনেট নেই"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"এই মুহূর্তে অ্যাক্সেস পয়েন্টের কোনও কানেকশন ফাঁকা নেই"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s এর মাধ্যমে সংযুক্ত হয়েছে"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s এর মাধ্যমে পাওয়া যাচ্ছে"</string> @@ -86,8 +84,7 @@ <string name="bluetooth_hid_profile_summary_connected" msgid="3381760054215168689">"ইনপুট ডিভাইসে সংযুক্ত"</string> <string name="bluetooth_pan_user_profile_summary_connected" msgid="6436258151814414028">"ইন্টারনেটের জন্য সংযুক্ত"</string> <string name="bluetooth_pan_nap_profile_summary_connected" msgid="1322694224800769308">"স্থানীয় ইন্টারনেটে চলছে"</string> - <!-- no translation found for bluetooth_pan_profile_summary_use_for (5736111170225304239) --> - <skip /> + <string name="bluetooth_pan_profile_summary_use_for" msgid="5736111170225304239">"ইন্টারনেটের জন্য ব্যবহার করুন"</string> <string name="bluetooth_map_profile_summary_use_for" msgid="5154200119919927434">"মানচিত্রের জন্য ব্যবহার করুন"</string> <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"সিম -এর অ্যাক্সেসের জন্য ব্যবহার করুন"</string> <string name="bluetooth_a2dp_profile_summary_use_for" msgid="4630849022250168427">"মিডিয়া অডিওয়ের জন্য ব্যবহার করুন"</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index c52c7ca0f7ac..d12ac8a5cb69 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -128,8 +128,8 @@ <string name="running_process_item_user_label" msgid="3129887865552025943">"Nutzer: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string> <string name="launch_defaults_some" msgid="313159469856372621">"Einige Standardeinstellungen festgelegt"</string> <string name="launch_defaults_none" msgid="4241129108140034876">"Keine Standardeinstellungen festgelegt"</string> - <string name="tts_settings" msgid="8186971894801348327">"Text-in-Sprache"</string> - <string name="tts_settings_title" msgid="1237820681016639683">"Text-in-Sprache-Ausgabe"</string> + <string name="tts_settings" msgid="8186971894801348327">"Sprachausgabe"</string> + <string name="tts_settings_title" msgid="1237820681016639683">"Sprachausgabe-Ausgabe"</string> <string name="tts_default_rate_title" msgid="6030550998379310088">"Sprechgeschwindigkeit"</string> <string name="tts_default_rate_summary" msgid="4061815292287182801">"Geschwindigkeit, mit der der Text gesprochen wird"</string> <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tonlage"</string> @@ -143,7 +143,7 @@ <string name="tts_install_data_title" msgid="4264378440508149986">"Sprachdaten installieren"</string> <string name="tts_install_data_summary" msgid="5742135732511822589">"Sprachdaten für Sprachsynthese installieren"</string> <string name="tts_engine_security_warning" msgid="8786238102020223650">"Dieses Sprachsynthesemodul kann den gesamten gesprochenen Text erfassen, einschließlich personenbezogener Daten wie Passwörter und Kreditkartennummern. Es ist Teil der App \"<xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>\". Möchtest du dieses Sprachsynthesemodul aktivieren?"</string> - <string name="tts_engine_network_required" msgid="1190837151485314743">"Für diese Sprache ist zur Text-in-Sprache-Ausgabe eine aktive Netzwerkverbindung erforderlich."</string> + <string name="tts_engine_network_required" msgid="1190837151485314743">"Für diese Sprache ist zur Sprachausgabe-Ausgabe eine aktive Netzwerkverbindung erforderlich."</string> <string name="tts_default_sample_string" msgid="4040835213373086322">"Dies ist ein Beispiel für Sprachsynthese."</string> <string name="tts_status_title" msgid="7268566550242584413">"Status der Standardsprache"</string> <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> wird vollständig unterstützt."</string> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index 826bab34d670..fcca9573d7b1 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -40,7 +40,7 @@ <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s के द्वारा उपलब्ध"</string> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s के द्वारा उपलब्ध"</string> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"कनेक्ट हो गया है, लेकिन इंटरनेट नहीं है"</string> - <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"एक्सेस पॉइंट फ़िलहाल भरा हुआ है"</string> + <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"एक्सेस प्वाइंट फ़िलहाल भरा हुआ है"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s के ज़रिए कनेक्ट"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s के ज़रिए उपलब्ध"</string> <string name="speed_label_very_slow" msgid="1867055264243608530">"अत्यधिक धीमी"</string> @@ -176,7 +176,7 @@ <string name="development_settings_not_available" msgid="4308569041701535607">"यह उपयोगकर्ता, डेवलपर के लिए सेटिंग और टूल का इस्तेमाल नहीं कर सकता"</string> <string name="vpn_settings_not_available" msgid="956841430176985598">"VPN सेटिंग इस उपयोगकर्ता के लिए उपलब्ध नहीं हैं"</string> <string name="tethering_settings_not_available" msgid="6765770438438291012">"टेदरिंग सेटिंग इस उपयोगकर्ता के लिए उपलब्ध नहीं हैं"</string> - <string name="apn_settings_not_available" msgid="7873729032165324000">"एक्सेस पॉइंट नाम सेटिंग इस उपयोगकर्ता के लिए मौजूद नहीं हैं"</string> + <string name="apn_settings_not_available" msgid="7873729032165324000">"एक्सेस प्वाइंट नाम सेटिंग इस उपयोगकर्ता के लिए मौजूद नहीं हैं"</string> <string name="enable_adb" msgid="7982306934419797485">"USB डीबग करना"</string> <string name="enable_adb_summary" msgid="4881186971746056635">"डीबग मोड जब USB कनेक्ट किया गया हो"</string> <string name="clear_adb_keys" msgid="4038889221503122743">"USB डीबग करने की मंज़ूरी रद्द करें"</string> @@ -201,7 +201,7 @@ <string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा हमेशा सक्रिय"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"हार्डवेयर से तेज़ी लाने के लिए टेदर करें"</string> <string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"बिना नाम वाले ब्लूटूथ डिवाइस दिखाएं"</string> - <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"पूर्ण वॉल्यूम अक्षम करें"</string> + <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ब्लूटूथ से आवाज़ के नियंत्रण की सुविधा रोकें"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"इन-बैंड रिंग करना चालू करें"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ब्लूटूथ AVRCP वर्शन"</string> <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ब्लूटूथ AVRCP वर्शन चुनें"</string> @@ -247,7 +247,7 @@ <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB पर ऐप की पुष्टि करें"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"नुकसानदेह व्यवहार के लिए ADB/ADT के द्वारा इंस्टॉल किए गए ऐप्स जाँचें."</string> <string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"बिना नाम वाले ब्लूटूथ डिवाइस (केवल MAC पते वाले) दिखाए जाएंगे"</string> - <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"दूरस्थ डिवाइस के साथ वॉल्यूम की समस्याओं जैसे अस्वीकार्य तेज़ वॉल्यूम या नियंत्रण की कमी की स्थिति में ब्लूटूथ पूर्ण वॉल्यूम सुविधा को अक्षम करता है."</string> + <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"दूर के डिवाइस पर आवाज़ बहुत बढ़ जाने या उससे नियंत्रण हटने जैसी समस्याएं होने पर, यह ब्लूटूथ के ज़रिए आवाज़ के नियंत्रण की सुविधा रोक देता है."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"फ़ोन की रिंगटोन को ब्लूटूथ हेडसेट पर बजने दें"</string> <string name="enable_terminal_title" msgid="95572094356054120">"स्थानीय टर्मिनल"</string> <string name="enable_terminal_summary" msgid="67667852659359206">"लोकल शेल तक पहुंचने की सुविधा देने वाले टर्मिनल ऐप को चालू करें"</string> @@ -317,8 +317,8 @@ <string name="enable_freeform_support" msgid="1461893351278940416">"फ़्रीफ़ॉर्म विंडो (एक साथ कई विंडो दिखाना) चालू करें"</string> <string name="enable_freeform_support_summary" msgid="8247310463288834487">"जाँच के लिए बनी फ़्रीफ़ॉर्म विंडो के लिए सहायता चालू करें."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"डेस्कटॉप बैकअप पासवर्ड"</string> - <string name="local_backup_password_summary_none" msgid="6951095485537767956">"डेस्कटॉप पूर्ण बैकअप वर्तमान में सुरक्षित नहीं हैं"</string> - <string name="local_backup_password_summary_change" msgid="5376206246809190364">"डेस्कटॉप के पूर्ण बैकअप का पासवर्ड बदलने या निकालने के लिए टैप करें"</string> + <string name="local_backup_password_summary_none" msgid="6951095485537767956">"डेस्कटॉप के पूरे बैक अप फ़िलहाल सुरक्षित नहीं हैं"</string> + <string name="local_backup_password_summary_change" msgid="5376206246809190364">"डेस्कटॉप के पूरे बैक अप का पासवर्ड बदलने या हटाने के लिए टैप करें"</string> <string name="local_backup_password_toast_success" msgid="582016086228434290">"नया बैकअप पासवर्ड सेट किया गया"</string> <string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"नया पासवर्ड तथा पुष्टि मेल नही खाते"</string> <string name="local_backup_password_toast_validation_failure" msgid="5646377234895626531">"सुरक्षित पासवर्ड सेट करने में विफल रहा"</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index 2873fb68ce5b..9caff100cb9d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -135,7 +135,8 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> if (newProfileState == BluetoothProfile.STATE_CONNECTED) { if (profile instanceof MapProfile) { profile.setPreferred(mDevice, true); - } else if (!mProfiles.contains(profile)) { + } + if (!mProfiles.contains(profile)) { mRemovedProfiles.remove(profile); mProfiles.add(profile); if (profile instanceof PanProfile && diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java index 9cda669379dd..991d9221c796 100755..100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java @@ -25,6 +25,7 @@ import android.bluetooth.BluetoothHidHost; import android.bluetooth.BluetoothMap; import android.bluetooth.BluetoothMapClient; import android.bluetooth.BluetoothPan; +import android.bluetooth.BluetoothPbap; import android.bluetooth.BluetoothPbapClient; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothUuid; @@ -140,9 +141,11 @@ public class LocalBluetoothProfileManager { BluetoothMap.ACTION_CONNECTION_STATE_CHANGED); } - //Create PBAP server profile, but do not add it to list of profiles - // as we do not need to monitor the profile as part of profile list + //Create PBAP server profile + if(DEBUG) Log.d(TAG, "Adding local PBAP profile"); mPbapProfile = new PbapServerProfile(context); + addProfile(mPbapProfile, PbapServerProfile.NAME, + BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED); if (DEBUG) Log.d(TAG, "LocalBluetoothProfileManager construction complete"); } @@ -495,6 +498,13 @@ public class LocalBluetoothProfileManager { mMapProfile.setPreferred(device, true); } + if ((mPbapProfile != null) && + (mPbapProfile.getConnectionStatus(device) == BluetoothProfile.STATE_CONNECTED)) { + profiles.add(mPbapProfile); + removedProfiles.remove(mPbapProfile); + mPbapProfile.setPreferred(device, true); + } + if (mMapClientProfile != null) { profiles.add(mMapClientProfile); removedProfiles.remove(mMapClientProfile); @@ -503,8 +513,6 @@ public class LocalBluetoothProfileManager { if (mUsePbapPce) { profiles.add(mPbapClientProfile); removedProfiles.remove(mPbapClientProfile); - profiles.remove(mPbapProfile); - removedProfiles.add(mPbapProfile); } if (DEBUG) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java index f3b69125cddc..58465f299578 100755 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java @@ -91,7 +91,7 @@ public class PbapServerProfile implements LocalBluetoothProfile { public boolean disconnect(BluetoothDevice device) { if (mService == null) return false; - return mService.disconnect(); + return mService.disconnect(device); } public int getConnectionStatus(BluetoothDevice device) { diff --git a/packages/SystemUI/res-keyguard/values-af/strings.xml b/packages/SystemUI/res-keyguard/values-af/strings.xml index c745fe8a0cd2..bf0d6799bfd1 100644 --- a/packages/SystemUI/res-keyguard/values-af/strings.xml +++ b/packages/SystemUI/res-keyguard/values-af/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Toestel is <xliff:g id="NUMBER_0">%d</xliff:g> uur lank nie ontsluit nie. Bevestig wagwoord.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Nie herken nie"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Voer SIM-PIN in; jy het <xliff:g id="NUMBER_1">%d</xliff:g> pogings oor.</item> + <item quantity="one">Verkeerde SIM-PIN. Jy het <xliff:g id="NUMBER_0">%d</xliff:g> poging oor voordat jy jou diensverskaffer moet kontak om jou toestel te ontsluit.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM is nou gedeaktiveer. Voer PUK-kode in om voort te gaan. Jy het <xliff:g id="_NUMBER_1">%d</xliff:g> pogings oor voordat die SIM permanent onbruikbaar word. Kontak die diensverskaffer vir besonderhede.</item> + <item quantity="one">SIM is nou gedeaktiveer. Voer PUK-kode in om voort te gaan. Jy het <xliff:g id="_NUMBER_0">%d</xliff:g> poging oor voordat die SIM permanent onbruikbaar word. Kontak die diensverskaffer vir besonderhede.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml index f4e3001b1a0d..340e5141c05d 100644 --- a/packages/SystemUI/res-keyguard/values-am/strings.xml +++ b/packages/SystemUI/res-keyguard/values-am/strings.xml @@ -135,4 +135,12 @@ <item quantity="other">መሣሪያው ለ<xliff:g id="NUMBER_1">%d</xliff:g> ሰዓቶች አልተከፈተም ነበር። የይለፍ ቃል ያረጋግጡ።</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"አልታወቀም"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">የሲም ፒን ያስገቡ፣ <xliff:g id="NUMBER_1">%d</xliff:g> ሙከራዎች ይቀረዎታል።</item> + <item quantity="other">የሲም ፒን ያስገቡ፣ <xliff:g id="NUMBER_1">%d</xliff:g> ሙከራዎች ይቀረዎታል።</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">ሲም አሁን ተሰናክሏል። ለመቀጠል የPUK ኮድ ያስገቡ። ሲም እስከመጨረሻው መጠቀም የማይቻል ከመሆኑ በፊት <xliff:g id="_NUMBER_1">%d</xliff:g> ሙከራዎች ይቀረዎታል። ዝርዝሮችን ለማግኘት የአገልግሎት አቅራቢን ያነጋግሩ።</item> + <item quantity="other">ሲም አሁን ተሰናክሏል። ለመቀጠል የPUK ኮድ ያስገቡ። ሲም እስከመጨረሻው መጠቀም የማይቻል ከመሆኑ በፊት <xliff:g id="_NUMBER_1">%d</xliff:g> ሙከራዎች ይቀረዎታል። ዝርዝሮችን ለማግኘት የአገልግሎት አቅራቢን ያነጋግሩ።</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml index 839fb873113e..7027d6f2e86c 100644 --- a/packages/SystemUI/res-keyguard/values-ar/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml @@ -159,4 +159,20 @@ <item quantity="one">لم يتم إلغاء تأمين الجهاز لمدة <xliff:g id="NUMBER_0">%d</xliff:g> ساعة. تأكيد كلمة المرور.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"لم يتم التعرف عليها"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="zero">أدخل رقم التعريف الشخصي لشريحة SIM، وتتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> محاولات.</item> + <item quantity="two">أدخل رقم التعريف الشخصي لشريحة SIM، وتتبقى لديك محاولتان (<xliff:g id="NUMBER_1">%d</xliff:g>).</item> + <item quantity="few">أدخل رقم التعريف الشخصي لشريحة SIM، وتتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> محاولات.</item> + <item quantity="many">أدخل رقم التعريف الشخصي لشريحة SIM، وتتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> محاولة.</item> + <item quantity="other">أدخل رقم التعريف الشخصي لشريحة SIM، وتتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> محاولة.</item> + <item quantity="one">أدخل رقم التعريف الشخصي لشريحة SIM، وتتبقى لديك محاولة واحدة (<xliff:g id="NUMBER_0">%d</xliff:g>) يجب أن تتصل بعدها بمشغّل شبكة الجوّال لإلغاء قفل الجهاز.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="zero">تم إيقاف شريحة SIM الآن. أدخل رمز PUK للمتابعة، وتتبقى لديك <xliff:g id="_NUMBER_1">%d</xliff:g> محاولة قبل أن تصبح شريحة SIM غير صالحة للاستخدام نهائيًا. ويمكنك الاتصال بمشغل شبكة الجوّال لمعرفة التفاصيل.</item> + <item quantity="two">تم إيقاف شريحة SIM الآن. أدخل رمز PUK للمتابعة، وتتبقى لديك محاولتان (<xliff:g id="_NUMBER_1">%d</xliff:g>) قبل أن تصبح شريحة SIM غير صالحة للاستخدام نهائيًا. ويمكنك الاتصال بمشغل شبكة الجوّال لمعرفة التفاصيل.</item> + <item quantity="few">تم إيقاف شريحة SIM الآن. أدخل رمز PUK للمتابعة، وتتبقى لديك <xliff:g id="_NUMBER_1">%d</xliff:g> محاولات قبل أن تصبح شريحة SIM غير صالحة للاستخدام نهائيًا. ويمكنك الاتصال بمشغل شبكة الجوّال لمعرفة التفاصيل.</item> + <item quantity="many">تم إيقاف شريحة SIM الآن. أدخل رمز PUK للمتابعة، وتتبقى لديك <xliff:g id="_NUMBER_1">%d</xliff:g> محاولة قبل أن تصبح شريحة SIM غير صالحة للاستخدام نهائيًا. ويمكنك الاتصال بمشغل شبكة الجوّال لمعرفة التفاصيل.</item> + <item quantity="other">تم إيقاف شريحة SIM الآن. أدخل رمز PUK للمتابعة، وتتبقى لديك <xliff:g id="_NUMBER_1">%d</xliff:g> محاولة قبل أن تصبح شريحة SIM غير صالحة للاستخدام نهائيًا. ويمكنك الاتصال بمشغل شبكة الجوّال لمعرفة التفاصيل.</item> + <item quantity="one">تم إيقاف شريحة SIM الآن. أدخل رمز PUK للمتابعة، وتتبقى لديك محاولة واحدة (<xliff:g id="_NUMBER_0">%d</xliff:g>) قبل أن تصبح شريحة SIM غير صالحة للاستخدام نهائيًا. ويمكنك الاتصال بمشغل شبكة الجوّال لمعرفة التفاصيل.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-az/strings.xml b/packages/SystemUI/res-keyguard/values-az/strings.xml index a868b7cbb033..b0503eade599 100644 --- a/packages/SystemUI/res-keyguard/values-az/strings.xml +++ b/packages/SystemUI/res-keyguard/values-az/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Cihaz <xliff:g id="NUMBER_0">%d</xliff:g> saat kiliddən çıxarılmayıb. Parolu təsdiq edin.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Tanınmır"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">SIM PIN-ni daxil edin, <xliff:g id="NUMBER_1">%d</xliff:g> cəhdiniz qalır.</item> + <item quantity="one">Yanlış SIM PIN kodu, cihazınızı kiliddən çıxarmaq üçün operatorunuzla əlaqə saxlamadan öncə <xliff:g id="NUMBER_0">%d</xliff:g> cəhdiniz qalır.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM indi deaktivdir. Davam etmək üçün PUK kodunu daxil edin. SIM birdəfəlik yararsız olmadan öncə <xliff:g id="_NUMBER_1">%d</xliff:g> cəhdiniz qalır. Ətraflı məlumat üçün operatorla əlaqə saxlayın.</item> + <item quantity="one">SIM indi deaktivdir. Davam etmək üçün PUK kodunu daxil edin. SIM birdəfəlik yararsız olmadan öncə <xliff:g id="_NUMBER_0">%d</xliff:g> cəhdiniz qalır. Ətraflı məlumat üçün operatorla əlaqə saxlayın.</item> + </plurals> </resources> 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 e24001ce56fa..079ba925b8c2 100644 --- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml @@ -141,4 +141,14 @@ <item quantity="other">Niste otključali uređaj <xliff:g id="NUMBER_1">%d</xliff:g> sati. Potvrdite lozinku.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Nije prepoznat"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Unesite PIN za SIM. Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaj.</item> + <item quantity="few">Unesite PIN za SIM. Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaja.</item> + <item quantity="other">Unesite PIN za SIM. Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaja.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">SIM je sada onemogućen. Unesite PUK kôd da biste nastavili. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaj pre nego što SIM postane trajno neupotrebljiv. Detaljne informacije potražite od mobilnog operatera.</item> + <item quantity="few">SIM je sada onemogućen. Unesite PUK kôd da biste nastavili. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaja pre nego što SIM postane trajno neupotrebljiv. Detaljne informacije potražite od mobilnog operatera.</item> + <item quantity="other">SIM je sada onemogućen. Unesite PUK kôd da biste nastavili. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaja pre nego što SIM postane trajno neupotrebljiv. Detaljne informacije potražite od mobilnog operatera.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-be/strings.xml b/packages/SystemUI/res-keyguard/values-be/strings.xml index 359271d5abdc..a3a38154968b 100644 --- a/packages/SystemUI/res-keyguard/values-be/strings.xml +++ b/packages/SystemUI/res-keyguard/values-be/strings.xml @@ -147,4 +147,16 @@ <item quantity="other">Прылада не была разблакіравана на працягу <xliff:g id="NUMBER_1">%d</xliff:g> гадзіны. Увядзіце пароль.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Не распазнаны"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Увядзіце PIN-код SIM-карты. У вас ёсць яшчэ <xliff:g id="NUMBER_1">%d</xliff:g> спроба.</item> + <item quantity="few">Увядзіце PIN-код SIM-карты. У вас ёсць яшчэ <xliff:g id="NUMBER_1">%d</xliff:g> спробы.</item> + <item quantity="many">Увядзіце PIN-код SIM-карты. У вас ёсць яшчэ <xliff:g id="NUMBER_1">%d</xliff:g> спроб.</item> + <item quantity="other">Увядзіце PIN-код SIM-карты. У вас ёсць яшчэ <xliff:g id="NUMBER_1">%d</xliff:g> спробы.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">SIM-карта заблакіравана. Каб працягнуць, увядзіце PUK-код. У вас ёсць яшчэ <xliff:g id="_NUMBER_1">%d</xliff:g> спроба, пасля чаго SIM-карта будзе заблакіравана назаўсёды. Звярніцеся да аператара, каб даведацца больш.</item> + <item quantity="few">SIM-карта заблакіравана. Каб працягнуць, увядзіце PUK-код. У вас ёсць яшчэ <xliff:g id="_NUMBER_1">%d</xliff:g> спробы, пасля чаго SIM-карта будзе заблакіравана назаўсёды. Звярніцеся да аператара, каб даведацца больш.</item> + <item quantity="many">SIM-карта заблакіравана. Каб працягнуць, увядзіце PUK-код. У вас ёсць яшчэ <xliff:g id="_NUMBER_1">%d</xliff:g> спроб, пасля чаго SIM-карта будзе заблакіравана назаўсёды. Звярніцеся да аператара, каб даведацца больш.</item> + <item quantity="other">SIM-карта заблакіравана. Каб працягнуць, увядзіце PUK-код. У вас ёсць яшчэ <xliff:g id="_NUMBER_1">%d</xliff:g> спробы, пасля чаго SIM-карта будзе заблакіравана назаўсёды. Звярніцеся да аператара, каб даведацца больш.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-bg/strings.xml b/packages/SystemUI/res-keyguard/values-bg/strings.xml index c098396bf8fd..87c7519fa91b 100644 --- a/packages/SystemUI/res-keyguard/values-bg/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bg/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Устройството не е отключвано от <xliff:g id="NUMBER_0">%d</xliff:g> час. Потвърдете паролата.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Не е разпознато"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Въведете ПИН кода за SIM картата – остават ви <xliff:g id="NUMBER_1">%d</xliff:g> опита.</item> + <item quantity="one">Въведете ПИН кода за SIM картата – остава ви <xliff:g id="NUMBER_0">%d</xliff:g> опит, преди да трябва да се свържете с оператора си, за да отключите устройството.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM картата вече е деактивирана. Въведете PUK кода, за да продължите. Остават ви <xliff:g id="_NUMBER_1">%d</xliff:g> опита, преди SIM картата да стане неизползваема завинаги. Свържете се с оператора за подробности.</item> + <item quantity="one">SIM картата вече е деактивирана. Въведете PUK кода, за да продължите. Остава ви <xliff:g id="_NUMBER_0">%d</xliff:g> опит, преди SIM картата да стане неизползваема завинаги. Свържете се с оператора за подробности.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml index 22e67b8dc363..5df39895f501 100644 --- a/packages/SystemUI/res-keyguard/values-bn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml @@ -135,4 +135,6 @@ <item quantity="other">ডিভাইসটি <xliff:g id="NUMBER_1">%d</xliff:g> ঘন্টা ধরে আনলক করা হয় নি। পাসওয়ার্ড নিশ্চিত করুন।</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"স্বীকৃত নয়"</string> + <!-- no translation found for kg_password_default_pin_message (6203676909479972943) --> + <!-- no translation found for kg_password_default_puk_message (8744416410184198352) --> </resources> diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml index 527122873f23..b74a6184d1a2 100644 --- a/packages/SystemUI/res-keyguard/values-bs/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml @@ -141,4 +141,14 @@ <item quantity="other">Uređaj nije otključavan <xliff:g id="NUMBER_1">%d</xliff:g> sati. Potvrdite lozinku.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Nije prepoznat"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Unesite PIN kôd za SIM. Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaj.</item> + <item quantity="few">Unesite PIN kôd za SIM. Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaja.</item> + <item quantity="other">Unesite PIN kôd za SIM. Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaja.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">SIM kartica je onemogućena. Unesite PUK kôd da nastavite. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaj prije nego što SIM kartica postane trajno neupotrebljiva. Obratite se operateru za više informacija.</item> + <item quantity="few">SIM kartica je onemogućena. Unesite PUK kôd da nastavite. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaja prije nego što SIM kartica postane trajno neupotrebljiva. Obratite se operateru za više informacija.</item> + <item quantity="other">SIM kartica je onemogućena. Unesite PUK kôd da nastavite. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaja prije nego što SIM kartica postane trajno neupotrebljiva. Obratite se operateru za više informacija.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml index 9aa8229d4a7b..dd2844abb6ec 100644 --- a/packages/SystemUI/res-keyguard/values-ca/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Fa <xliff:g id="NUMBER_0">%d</xliff:g> hora que no es desbloqueja el dispositiu. Confirma la contrasenya.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"No s\'ha reconegut"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Introdueix el PIN de la SIM. Et queden <xliff:g id="NUMBER_1">%d</xliff:g> intents.</item> + <item quantity="one">Introdueix el PIN de la SIM. Et queda <xliff:g id="NUMBER_0">%d</xliff:g> intent; si no l\'encertes, contacta amb l\'operador de telefonia mòbil per desbloquejar el dispositiu.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">La targeta SIM s\'ha desactivat. Introdueix el codi PUK per continuar. Et queden <xliff:g id="_NUMBER_1">%d</xliff:g> intents; si no l\'encertes, la SIM no es podrà tornar a fer servir. Contacta amb l\'operador de telefonia mòbil per obtenir-ne més informació.</item> + <item quantity="one">La targeta SIM s\'ha desactivat. Introdueix el codi PUK per continuar. Et queda <xliff:g id="_NUMBER_0">%d</xliff:g> intent; si no l\'encertes, la SIM no es podrà tornar a fer servir. Contacta amb l\'operador de telefonia mòbil per obtenir-ne més informació.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml index f5864cd5e0f3..cf7abf121301 100644 --- a/packages/SystemUI/res-keyguard/values-cs/strings.xml +++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml @@ -147,4 +147,16 @@ <item quantity="one">Zařízení již <xliff:g id="NUMBER_0">%d</xliff:g> hodinu nebylo odemknuto. Zadejte heslo.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Nerozpoznáno"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="few">Zadejte PIN SIM karty. Zbývají <xliff:g id="NUMBER_1">%d</xliff:g> pokusy.</item> + <item quantity="many">Zadejte PIN SIM karty. Zbývá <xliff:g id="NUMBER_1">%d</xliff:g> pokusu.</item> + <item quantity="other">Zadejte PIN SIM karty. Zbývá <xliff:g id="NUMBER_1">%d</xliff:g> pokusů.</item> + <item quantity="one">Zadejte PIN SIM karty. Zbývá <xliff:g id="NUMBER_0">%d</xliff:g> pokus, poté bude muset zařízení odemknout operátor.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="few">SIM karta je nyní zablokována. Chcete-li pokračovat, zadejte kód PUK. Máte ještě <xliff:g id="_NUMBER_1">%d</xliff:g> pokusy, poté bude SIM karta natrvalo zablokována. Podrobnosti vám poskytne operátor.</item> + <item quantity="many">SIM karta je nyní zablokována. Chcete-li pokračovat, zadejte kód PUK. Máte ještě <xliff:g id="_NUMBER_1">%d</xliff:g> pokusu, poté bude SIM karta natrvalo zablokována. Podrobnosti vám poskytne operátor.</item> + <item quantity="other">SIM karta je nyní zablokována. Chcete-li pokračovat, zadejte kód PUK. Máte ještě <xliff:g id="_NUMBER_1">%d</xliff:g> pokusů, poté bude SIM karta natrvalo zablokována. Podrobnosti vám poskytne operátor.</item> + <item quantity="one">SIM karta je nyní zablokována. Chcete-li pokračovat, zadejte kód PUK. Máte ještě <xliff:g id="_NUMBER_0">%d</xliff:g> pokus, poté bude SIM karta natrvalo zablokována. Podrobnosti vám poskytne operátor.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml index cb9989fc2676..156da2e3cc2d 100644 --- a/packages/SystemUI/res-keyguard/values-da/strings.xml +++ b/packages/SystemUI/res-keyguard/values-da/strings.xml @@ -135,4 +135,12 @@ <item quantity="other">Enheden blev sidst låst op for <xliff:g id="NUMBER_1">%d</xliff:g> timer siden. Bekræft adgangskoden.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Ikke genkendt"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Indtast pinkoden til SIM-kortet. Du har <xliff:g id="NUMBER_1">%d</xliff:g> forsøg tilbage.</item> + <item quantity="other">Indtast pinkoden til SIM-kortet. Du har <xliff:g id="NUMBER_1">%d</xliff:g> forsøg tilbage.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">SIM-kortet er nu deaktiveret. Indtast PUK-koden for at fortsætte. Du har <xliff:g id="_NUMBER_1">%d</xliff:g> forsøg tilbage, før SIM-kortet bliver permanent ubrugeligt. Kontakt dit mobilselskab for at få flere oplysninger.</item> + <item quantity="other">SIM-kortet er nu deaktiveret. Indtast PUK-koden for at fortsætte. Du har <xliff:g id="_NUMBER_1">%d</xliff:g> forsøg tilbage, før SIM-kortet bliver permanent ubrugeligt. Kontakt dit mobilselskab for at få flere oplysninger.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml index 372ca1626d57..852a9c1d246c 100644 --- a/packages/SystemUI/res-keyguard/values-de/strings.xml +++ b/packages/SystemUI/res-keyguard/values-de/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Das Gerät wurde seit <xliff:g id="NUMBER_0">%d</xliff:g> Stunde nicht mehr entsperrt. Bitte bestätige das Passwort.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Nicht erkannt"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Gib die PIN für die SIM-Karte ein. Du hast noch <xliff:g id="NUMBER_1">%d</xliff:g> Versuche.</item> + <item quantity="one">Gib die PIN für die SIM-Karte ein. Du hast noch <xliff:g id="NUMBER_0">%d</xliff:g> Versuch, bevor das Gerät vom Mobilfunkanbieter entsperrt werden muss.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">Die SIM-Karte ist jetzt deaktiviert. Gib den PUK-Code ein, um fortzufahren. Du hast noch <xliff:g id="_NUMBER_1">%d</xliff:g> Versuche, bevor die SIM-Karte endgültig gesperrt wird. Weitere Informationen erhältst du von deinem Mobilfunkanbieter.</item> + <item quantity="one">Die SIM-Karte ist jetzt deaktiviert. Gib den PUK-Code ein, um fortzufahren. Du hast noch <xliff:g id="_NUMBER_0">%d</xliff:g> Versuch, bevor die SIM-Karte endgültig gesperrt wird. Weitere Informationen erhältst du von deinem Mobilfunkanbieter.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-el/strings.xml b/packages/SystemUI/res-keyguard/values-el/strings.xml index 48faeba8c40c..0127ef163af9 100644 --- a/packages/SystemUI/res-keyguard/values-el/strings.xml +++ b/packages/SystemUI/res-keyguard/values-el/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Η συσκευή δεν έχει ξεκλειδωθεί εδώ και <xliff:g id="NUMBER_0">%d</xliff:g> ώρα. Επιβεβαιώστε τον κωδικό πρόσβασης.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Δεν αναγνωρίστηκε"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Καταχωρίστε τον αριθμό PIN της κάρτας SIM. Απομένουν <xliff:g id="NUMBER_1">%d</xliff:g> ακόμη προσπάθειες.</item> + <item quantity="one">Εσφαλμένος αριθμός PIN κάρτας SIM. Απομένει άλλη <xliff:g id="NUMBER_0">%d</xliff:g> προσπάθεια. Στη συνέχεια, θα πρέπει να επικοινωνήσετε με τον πάροχο κινητής τηλεφωνίας, για να ξεκλειδώσετε τη συσκευή.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">Η κάρτα SIM απενεργοποιήθηκε. Καταχωρίστε τον κωδικό PUK, για να συνεχίσετε. Απομένουν <xliff:g id="_NUMBER_1">%d</xliff:g> ακόμη προσπάθειες προτού να μην είναι πλέον δυνατή η χρήση της κάρτας SIM. Επικοινωνήστε με την εταιρεία κινητής τηλεφωνίας για λεπτομέρειες.</item> + <item quantity="one">Η κάρτα SIM απενεργοποιήθηκε. Καταχωρίστε τον κωδικό PUK, για να συνεχίσετε. Απομένει <xliff:g id="_NUMBER_0">%d</xliff:g> ακόμη προσπάθεια προτού να μην είναι πλέον δυνατή η χρήση της κάρτας SIM. Επικοινωνήστε με την εταιρεία κινητής τηλεφωνίας για λεπτομέρειες.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml index b7c026f9caab..df0c45b54bbb 100644 --- a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml +++ b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Hace <xliff:g id="NUMBER_0">%d</xliff:g> hora que no se desbloquea el dispositivo. Confirma la contraseña.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"No se reconoció"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Ingresa el PIN de la SIM. Te quedan <xliff:g id="NUMBER_1">%d</xliff:g> intentos más.</item> + <item quantity="one">Ingresa el PIN de la SIM. Te queda <xliff:g id="NUMBER_0">%d</xliff:g> intento antes de que debas comunicarte con tu proveedor para desbloquear el dispositivo.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">Se inhabilitó la SIM. Para continuar, ingresa el código PUK. Te quedan <xliff:g id="_NUMBER_1">%d</xliff:g> intentos más antes de que la SIM quede inutilizable permanentemente. Comunícate con tu proveedor para obtener más detalles.</item> + <item quantity="one">Se inhabilitó la SIM. Para continuar, ingresa el código PUK. Te queda <xliff:g id="_NUMBER_0">%d</xliff:g> intento más antes de que la SIM quede inutilizable permanentemente. Comunícate con tu proveedor para obtener más detalles.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml index ac99a84a0b83..ec36fd73966f 100644 --- a/packages/SystemUI/res-keyguard/values-es/strings.xml +++ b/packages/SystemUI/res-keyguard/values-es/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">El dispositivo no se ha desbloqueado durante <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirma la contraseña.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"No reconocido"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Introduce el PIN de la tarjeta SIM. Te quedan <xliff:g id="NUMBER_1">%d</xliff:g> intentos.</item> + <item quantity="one">Introduce el PIN de la tarjeta SIM. Te queda <xliff:g id="NUMBER_0">%d</xliff:g> para tener que ponerte en contacto con tu operador para desbloquear el dispositivo.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">La tarjeta SIM está inhabilitada. Introduce el código PUK para continuar. Te quedan <xliff:g id="_NUMBER_1">%d</xliff:g> intentos para que la tarjeta SIM quede inservible de forma permanente. Ponte en contacto con tu operador para obtener más información.</item> + <item quantity="one">La tarjeta SIM está inhabilitada. Introduce el código PUK para continuar. Te queda <xliff:g id="_NUMBER_0">%d</xliff:g> intento para que la tarjeta SIM quede inservible de forma permanente. Ponte en contacto con tu operador para obtener más información.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-et/strings.xml b/packages/SystemUI/res-keyguard/values-et/strings.xml index b2c00bf5b7b8..bca98ef32af3 100644 --- a/packages/SystemUI/res-keyguard/values-et/strings.xml +++ b/packages/SystemUI/res-keyguard/values-et/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Seadet pole avatud <xliff:g id="NUMBER_0">%d</xliff:g> tund. Kinnitage parool.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Ei tuvastatud"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Sisestage SIM-kaardi PIN-kood. Jäänud on <xliff:g id="NUMBER_1">%d</xliff:g> katset.</item> + <item quantity="one">Sisestage SIM-kaardi PIN-kood. Jäänud on <xliff:g id="NUMBER_0">%d</xliff:g> katse enne, kui peate seadme avamiseks ühendust võtma operaatoriga.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM-kaart on nüüd keelatud. Jätkamiseks sisestage PUK-kood. Teil on jäänud veel <xliff:g id="_NUMBER_1">%d</xliff:g> katset enne, kui SIM-kaart püsivalt lukustatakse. Lisateavet küsige operaatorilt.</item> + <item quantity="one">SIM-kaart on nüüd keelatud. Jätkamiseks sisestage PUK-kood. Teil on jäänud veel <xliff:g id="_NUMBER_0">%d</xliff:g> katse enne, kui SIM-kaart püsivalt lukustatakse. Lisateavet küsige operaatorilt.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml index c8eab84032f7..3d79ae2a4825 100644 --- a/packages/SystemUI/res-keyguard/values-eu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Gailua ez da desblokeatu <xliff:g id="NUMBER_0">%d</xliff:g> orduz. Berretsi pasahitza.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Ez da ezagutu"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Idatzi SIM txartelaren PIN kodea. <xliff:g id="NUMBER_1">%d</xliff:g> saiakera geratzen zaizkizu.</item> + <item quantity="one">Idatzi SIM txartelaren PIN kodea. <xliff:g id="NUMBER_0">%d</xliff:g> saiakera geratzen zaizu; oker idatziz gero, operadoreari eskatu beharko diozu gailua desblokeatzeko.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">Desgaitu egin da SIM txartela. Aurrera egiteko, idatzi PUK kodea. <xliff:g id="_NUMBER_1">%d</xliff:g> saiakera geratzen zaizkizu SIM txartela betiko erabilgaitz geratu aurretik. Xehetasunak lortzeko, jarri operadorearekin harremanetan.</item> + <item quantity="one">Desgaitu egin da SIM txartela. Aurrera egiteko, idatzi PUK kodea. <xliff:g id="_NUMBER_0">%d</xliff:g> saiakera geratzen zaizu SIM txartela betiko erabilgaitz geratu aurretik. Xehetasunak lortzeko, jarri operadorearekin harremanetan.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-fa/strings.xml b/packages/SystemUI/res-keyguard/values-fa/strings.xml index 819b0e86e8bd..ce46e6ae4b05 100644 --- a/packages/SystemUI/res-keyguard/values-fa/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fa/strings.xml @@ -135,4 +135,12 @@ <item quantity="other">قفل دستگاه <xliff:g id="NUMBER_1">%d</xliff:g> ساعت باز نشده است. گذرواژه را تأیید کنید.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"شناسایی نشد"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">پین سیمکارت را وارد کنید. <xliff:g id="NUMBER_1">%d</xliff:g> تلاش دیگری باقی مانده است.</item> + <item quantity="other">پین سیمکارت را وارد کنید. <xliff:g id="NUMBER_1">%d</xliff:g> تلاش دیگری باقی مانده است.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">سیمکارت اکنون غیرفعال است. برای ادامه دادن کد PUK را وارد کنید. <xliff:g id="_NUMBER_1">%d</xliff:g> تلاش دیگر باقی مانده است و پس از آن سیمکارت برای همیشه غیرقابلاستفاده میشود. برای اطلاع از جزئیات با شرکت مخابراتی تماس بگیرید.</item> + <item quantity="other">سیمکارت اکنون غیرفعال است. برای ادامه دادن کد PUK را وارد کنید. <xliff:g id="_NUMBER_1">%d</xliff:g> تلاش دیگر باقی مانده است و پس از آن سیمکارت برای همیشه غیرقابلاستفاده میشود. برای اطلاع از جزئیات با شرکت مخابراتی تماس بگیرید.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml index dc2a4411b268..2b14e3c977bc 100644 --- a/packages/SystemUI/res-keyguard/values-fi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Laitteen lukitusta ei ole avattu <xliff:g id="NUMBER_0">%d</xliff:g> tuntiin. Vahvista salasana.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Ei tunnistettu"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Anna SIM-kortin PIN-koodi. Sinulla on <xliff:g id="NUMBER_1">%d</xliff:g> yritystä jäljellä.</item> + <item quantity="one">Anna SIM-kortin PIN-koodi. <xliff:g id="NUMBER_0">%d</xliff:g> yrityksen jälkeen laite lukittuu, ja vain operaattori voi avata sen.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM-kortti on nyt lukittu. Anna PUK-koodi, niin voit jatkaa. Sinulla on <xliff:g id="_NUMBER_1">%d</xliff:g> yritystä jäljellä, ennen kuin SIM-kortti poistuu pysyvästi käytöstä. Pyydä lisätietoja operaattoriltasi.</item> + <item quantity="one">SIM-kortti on nyt lukittu. Anna PUK-koodi, niin voit jatkaa. Sinulla on <xliff:g id="_NUMBER_0">%d</xliff:g> yritys jäljellä, ennen kuin SIM-kortti poistuu pysyvästi käytöstä. Pyydä lisätietoja operaattoriltasi.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml index 8e614e04d560..b033311f37b9 100644 --- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml @@ -135,4 +135,12 @@ <item quantity="other">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heures. Confirmez le mot de passe.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Doigt non reconnu"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Entrez le NIP de votre carte SIM. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative.</item> + <item quantity="other">Entrez le NIP de votre carte SIM. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">La carte SIM est maintenant désactivée. Entrez le code PUK pour continuer. Il vous reste <xliff:g id="_NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM devienne définitivement inutilisable. Pour obtenir plus de détails, communiquez avec votre fournisseur de services.</item> + <item quantity="other">La carte SIM est maintenant désactivée. Entrez le code PUK pour continuer. Il vous reste <xliff:g id="_NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM devienne définitivement inutilisable. Pour obtenir plus de détails, communiquez avec votre fournisseur de services.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml index b3ed4c55598b..34b638e7a4c8 100644 --- a/packages/SystemUI/res-keyguard/values-fr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml @@ -135,4 +135,12 @@ <item quantity="other">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heures. Confirmez le mot de passe.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Non reconnu"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Saisissez le code PIN de la carte SIM. <xliff:g id="NUMBER_1">%d</xliff:g> tentative restante.</item> + <item quantity="other">Saisissez le code PIN de la carte SIM. <xliff:g id="NUMBER_1">%d</xliff:g> tentatives restantes.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">La carte SIM est maintenant désactivée. Saisissez le code PUK pour continuer. Il vous reste <xliff:g id="_NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM ne devienne définitivement inutilisable. Pour de plus amples informations, veuillez contacter votre opérateur.</item> + <item quantity="other">La carte SIM est maintenant désactivée. Saisissez le code PUK pour continuer. Il vous reste <xliff:g id="_NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM ne devienne définitivement inutilisable. Pour de plus amples informations, veuillez contacter votre opérateur.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml index 7be5f41fa409..e21e8441f7f8 100644 --- a/packages/SystemUI/res-keyguard/values-gl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">O dispositivo non se desbloqueou durante <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirma o contrasinal.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Non se recoñece"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Introduce o código PIN da SIM. Quédanche <xliff:g id="NUMBER_1">%d</xliff:g> intentos.</item> + <item quantity="one">Introduce o código PIN da SIM. Quédache <xliff:g id="NUMBER_0">%d</xliff:g> intento antes de que teñas que contactar co operador para desbloquear o dispositivo.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">A SIM está desactivada. Introduce o código PUK para continuar. Quédanche <xliff:g id="_NUMBER_1">%d</xliff:g> intentos antes de que a SIM quede inutilizable para sempre. Contacta co operador para obter información.</item> + <item quantity="one">A SIM está desactivada. Introduce o código PUK para continuar. Quédache <xliff:g id="_NUMBER_0">%d</xliff:g> intento antes de que a SIM quede inutilizable para sempre. Contacta co operador para obter información.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml index 48aa75b9f29a..a6ee9a65f424 100644 --- a/packages/SystemUI/res-keyguard/values-gu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml @@ -135,4 +135,6 @@ <item quantity="other">ઉપકરણને <xliff:g id="NUMBER_1">%d</xliff:g> કલાક માટે અનલૉક કરવામાં આવ્યું નથી. પાસવર્ડની પુષ્ટિ કરો.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"ઓળખાયેલ નથી"</string> + <!-- no translation found for kg_password_default_pin_message (6203676909479972943) --> + <!-- no translation found for kg_password_default_puk_message (8744416410184198352) --> </resources> diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml index 40966c0bbaff..641c0727085a 100644 --- a/packages/SystemUI/res-keyguard/values-hi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml @@ -135,4 +135,12 @@ <item quantity="other">डिवाइस को <xliff:g id="NUMBER_1">%d</xliff:g> घंटों से अनलॉक नहीं किया गया है. पासवर्ड की पुष्टि करें.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"उंगली की पहचान नहीं हो सकी"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">सिम का पिन डालें, आपके पास <xliff:g id="NUMBER_1">%d</xliff:g> मौके बचे हैं.</item> + <item quantity="other">सिम का पिन डालें, आपके पास <xliff:g id="NUMBER_1">%d</xliff:g> मौके बचे हैं.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">सिम बंद कर दिया गया है. जारी रखने के लिए PUK कोड डालें. आपके पास <xliff:g id="_NUMBER_1">%d</xliff:g> मौके बचे हैं, उसके बाद, सिम हमेशा के लिए काम करना बंद कर देगा. जानकारी के लिए, मोबाइल और इंटरनेट सेवा देने वाली कंपनी से संपर्क करें.</item> + <item quantity="other">सिम बंद कर दिया गया है. जारी रखने के लिए PUK कोड डालें. आपके पास <xliff:g id="_NUMBER_1">%d</xliff:g> मौके बचे हैं, उसके बाद, सिम हमेशा के लिए काम करना बंद कर देगा. जानकारी के लिए, मोबाइल और इंटरनेट सेवा देने वाली कंपनी से संपर्क करें.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-hr/strings.xml b/packages/SystemUI/res-keyguard/values-hr/strings.xml index 4247ede73585..cfdf5cd8662f 100644 --- a/packages/SystemUI/res-keyguard/values-hr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hr/strings.xml @@ -141,4 +141,14 @@ <item quantity="other">Uređaj nije bio otključan <xliff:g id="NUMBER_1">%d</xliff:g> sati. Potvrdite zaporku.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Nije prepoznat"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Unesite PIN za SIM. Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaj.</item> + <item quantity="few">Unesite PIN za SIM. Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaja.</item> + <item quantity="other">Unesite PIN za SIM. Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaja.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">SIM je sada onemogućen. Unesite PUK kôd da biste nastavili. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaj prije nego što SIM kartica postane trajno neupotrebljiva. Više informacija zatražite od mobilnog operatera.</item> + <item quantity="few">SIM je sada onemogućen. Unesite PUK kôd da biste nastavili. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaja prije nego što SIM kartica postane trajno neupotrebljiva. Više informacija zatražite od mobilnog operatera.</item> + <item quantity="other">SIM je sada onemogućen. Unesite PUK kôd da biste nastavili. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaja prije nego što SIM kartica postane trajno neupotrebljiva. Više informacija zatražite od mobilnog operatera.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-hu/strings.xml b/packages/SystemUI/res-keyguard/values-hu/strings.xml index 30ccb67a35e8..71f34a9b639f 100644 --- a/packages/SystemUI/res-keyguard/values-hu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hu/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Az eszköz zárolása <xliff:g id="NUMBER_0">%d</xliff:g> órája nem lett feloldva. Erősítse meg a jelszót.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Nem sikerült felismerni"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Adja meg a SIM-kártya PIN-kódját. <xliff:g id="NUMBER_1">%d</xliff:g> próbálkozása maradt.</item> + <item quantity="one">Adja meg a SIM-kártya PIN-kódját. <xliff:g id="NUMBER_0">%d</xliff:g> próbálkozása maradt. Ha elfogynak a próbálkozási lehetőségek, az eszköz feloldásához fel kell vennie a kapcsolatot szolgáltatójával.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">A SIM-kártya le van tiltva. A folytatáshoz adja meg a PUK-kódot. Még <xliff:g id="_NUMBER_1">%d</xliff:g> próbálkozása van, mielőtt végleg használhatatlanná válik a SIM-kártya. További információért forduljon a szolgáltatóhoz.</item> + <item quantity="one">A SIM-kártya le van tiltva. A folytatáshoz adja meg a PUK-kódot. Még <xliff:g id="_NUMBER_0">%d</xliff:g> próbálkozása van, mielőtt végleg használhatatlanná válik a SIM-kártya. További információért forduljon a szolgáltatóhoz.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-hy/strings.xml b/packages/SystemUI/res-keyguard/values-hy/strings.xml index 7914b5f792a5..29369351f8a6 100644 --- a/packages/SystemUI/res-keyguard/values-hy/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hy/strings.xml @@ -135,4 +135,12 @@ <item quantity="other">Սարքը չի ապակողպվել <xliff:g id="NUMBER_1">%d</xliff:g> ժամվա ընթացքում: Հաստատեք գաղտնաբառը:</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Չճանաչվեց"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Մուտքագրեք SIM քարտի PIN կոդը: Մնացել է <xliff:g id="NUMBER_1">%d</xliff:g> փորձ:</item> + <item quantity="other">Մուտքագրեք SIM քարտի PIN կոդը: Մնացել է <xliff:g id="NUMBER_1">%d</xliff:g> փորձ:</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">SIM քարտն անջատված է: Շարունակելու համար մուտքագրեք PUK կոդը: Մնացել է <xliff:g id="_NUMBER_1">%d</xliff:g> փորձ, որից հետո SIM քարտն այլևս հնարավոր չի լինի օգտագործել: Մանրամասների համար դիմեք օպերատորին:</item> + <item quantity="other">SIM քարտն անջատված է: Շարունակելու համար մուտքագրեք PUK կոդը: Մնացել է <xliff:g id="_NUMBER_1">%d</xliff:g> փորձ, որից հետո SIM քարտն այլևս հնարավոր չի լինի օգտագործել: Մանրամասների համար դիմեք օպերատորին:</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml index e417a3f44918..ee3621c35932 100644 --- a/packages/SystemUI/res-keyguard/values-in/strings.xml +++ b/packages/SystemUI/res-keyguard/values-in/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Perangkat belum dibuka kuncinya selama <xliff:g id="NUMBER_0">%d</xliff:g> jam. Konfirmasi sandi.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Tidak dikenali"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Masukkan PIN SIM, tersisa <xliff:g id="NUMBER_1">%d</xliff:g> percobaan.</item> + <item quantity="one">Masukkan PIN SIM, tersisa <xliff:g id="NUMBER_0">%d</xliff:g> percobaan sebelum Anda harus menghubungi operator untuk membuka kunci perangkat.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM kini dinonaktifkan. Masukkan kode PUK untuk melanjutkan. Tersisa <xliff:g id="_NUMBER_1">%d</xliff:g> percobaan sebelum SIM tidak dapat digunakan secara permanen. Hubungi operator untuk mengetahui detailnya.</item> + <item quantity="one">SIM kini dinonaktifkan. Masukkan kode PUK untuk melanjutkan. Tersisa <xliff:g id="_NUMBER_0">%d</xliff:g> percobaan sebelum SIM tidak dapat digunakan secara permanen. Hubungi operator untuk mengetahui detailnya.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-is/strings.xml b/packages/SystemUI/res-keyguard/values-is/strings.xml index 6d92dbae3489..cead5c4c97f4 100644 --- a/packages/SystemUI/res-keyguard/values-is/strings.xml +++ b/packages/SystemUI/res-keyguard/values-is/strings.xml @@ -135,4 +135,12 @@ <item quantity="other">Tækið hefur ekki verið tekið úr lás í <xliff:g id="NUMBER_1">%d</xliff:g> klukkustundir. Staðfestu aðgangsorðið.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Þekktist ekki"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Sláðu inn PIN-númer SIM-korts. Það er <xliff:g id="NUMBER_1">%d</xliff:g> tilraun eftir.</item> + <item quantity="other">Sláðu inn PIN-númer SIM-korts. Það eru <xliff:g id="NUMBER_1">%d</xliff:g> tilraunir eftir.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">SIM-kortið er nú óvirkt. Sláðu inn PUK-númer til að halda áfram. Það er <xliff:g id="_NUMBER_1">%d</xliff:g> tilraun eftir þar til SIM-kortið verður ónothæft til frambúðar. Hafðu samband við símafyrirtækið til að fá upplýsingar.</item> + <item quantity="other">SIM-kortið er nú óvirkt. Sláðu inn PUK-númer til að halda áfram. Það eru <xliff:g id="_NUMBER_1">%d</xliff:g> tilraunir eftir þar til SIM-kortið verður ónothæft til frambúðar. Hafðu samband við símafyrirtækið til að fá upplýsingar.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml index f449202a13d9..001f90cff98c 100644 --- a/packages/SystemUI/res-keyguard/values-it/strings.xml +++ b/packages/SystemUI/res-keyguard/values-it/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Il dispositivo non viene sbloccato da <xliff:g id="NUMBER_0">%d</xliff:g> ora. Conferma la password.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Non riconosciuta"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Inserisci il codice PIN della SIM. Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione.</item> + <item quantity="one">Inserisci il codice PIN della SIM. Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione, dopodiché dovrai contattare l\'operatore per sbloccare il dispositivo.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora <xliff:g id="_NUMBER_1">%d</xliff:g> tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile. Contatta l\'operatore per avere informazioni dettagliate.</item> + <item quantity="one">La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora <xliff:g id="_NUMBER_0">%d</xliff:g> tentativo a disposizione prima che la SIM diventi definitivamente inutilizzabile. Contatta l\'operatore per avere informazioni dettagliate.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml index cb61b7dffb8a..8be3a8922e95 100644 --- a/packages/SystemUI/res-keyguard/values-iw/strings.xml +++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml @@ -147,4 +147,16 @@ <item quantity="one">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_0">%d</xliff:g> שעה. הזן את הסיסמה.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"לא זוהתה"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="two">יש להזין PIN של כרטיס SIM, נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות נוספים.</item> + <item quantity="many">יש להזין PIN של כרטיס SIM, נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות נוספים.</item> + <item quantity="other">יש להזין PIN של כרטיס SIM, נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות נוספים.</item> + <item quantity="one">יש להזין PIN של כרטיס SIM. נותר לך <xliff:g id="NUMBER_0">%d</xliff:g> ניסיון נוסף לפני שיהיה צורך ליצור קשר עם הספק כדי לבטל את נעילת המכשיר.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="two">כרטיס ה-SIM מושבת כעת. יש להזין קוד PUK כדי להמשיך. נותרו לך <xliff:g id="_NUMBER_1">%d</xliff:g> ניסיונות נוספים לפני שכרטיס ה-SIM ינעל לצמיתות. למידע נוסף, ניתן לפנות לספק שלך.</item> + <item quantity="many">כרטיס ה-SIM מושבת כעת. יש להזין קוד PUK כדי להמשיך. נותרו לך <xliff:g id="_NUMBER_1">%d</xliff:g> ניסיונות נוספים לפני שכרטיס ה-SIM ינעל לצמיתות. למידע נוסף, ניתן לפנות לספק שלך.</item> + <item quantity="other">כרטיס ה-SIM מושבת כעת. יש להזין קוד PUK כדי להמשיך. נותרו לך <xliff:g id="_NUMBER_1">%d</xliff:g> ניסיונות נוספים לפני שכרטיס ה-SIM ינעל לצמיתות. למידע נוסף, ניתן לפנות לספק שלך.</item> + <item quantity="one">כרטיס ה-SIM מושבת כעת. יש להזין קוד PUK כדי להמשיך. נותר לך <xliff:g id="_NUMBER_0">%d</xliff:g> ניסיון נוסף לפני שכרטיס ה-SIM ינעל לצמיתות. למידע נוסף, ניתן לפנות לספק שלך.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml index 8aa2e47eec98..6bdc20010b21 100644 --- a/packages/SystemUI/res-keyguard/values-ja/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">端末のロックが <xliff:g id="NUMBER_0">%d</xliff:g> 時間、解除されていません。パスワードを確認してください。</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"認識されませんでした"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">SIM PIN を入力してください。入力できるのはあと <xliff:g id="NUMBER_1">%d</xliff:g> 回です。</item> + <item quantity="one">SIM PIN を入力してください。入力できるのはあと <xliff:g id="NUMBER_0">%d</xliff:g> 回です。この回数を超えた場合は、携帯通信会社にお問い合わせください。</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM が無効になりました。続行するには PUK コードを入力してください。入力できるのはあと <xliff:g id="_NUMBER_1">%d</xliff:g> 回です。この回数を超えると SIM は完全に使用できなくなります。詳しくは携帯通信会社にお問い合わせください。</item> + <item quantity="one">SIM が無効になりました。続行するには PUK コードを入力してください。入力できるのはあと <xliff:g id="_NUMBER_0">%d</xliff:g> 回です。この回数を超えると SIM は完全に使用できなくなります。詳しくは携帯通信会社にお問い合わせください。</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ka/strings.xml b/packages/SystemUI/res-keyguard/values-ka/strings.xml index 1ff7a965c3de..31ccaae0d574 100644 --- a/packages/SystemUI/res-keyguard/values-ka/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ka/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">მოწყობილობა არ განბლოკილა <xliff:g id="NUMBER_0">%d</xliff:g> საათის განმავლობაში. დაადასტურეთ პაროლი.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"არ არის ამოცნობილი"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">შეიყვანეთ SIM ბარათის PIN-კოდი. თქვენ დაგრჩათ <xliff:g id="NUMBER_1">%d</xliff:g> მცდელობა.</item> + <item quantity="one">შეიყვანეთ SIM ბარათის PIN-კოდი. თქვენ დაგრჩათ <xliff:g id="NUMBER_0">%d</xliff:g> მცდელობა, რომლის შემდეგაც მოწყობილობის განსაბლოკად დაგჭირდებათ თქვენს ოპერატორთან დაკავშირება.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM ბარათი ახლა დეაქტივირებულია. გასაგრძელებლად შეიყვანეთ PUK-კოდი. თქვენ დაგრჩათ <xliff:g id="_NUMBER_1">%d</xliff:g> მცდელობა, სანამ SIM სამუდამოდ გამოუსადეგარი გახდება. დეტალური ინფორმაციისთვის დაუკავშირდით თქვენს ოპერატორს.</item> + <item quantity="one">SIM ბარათი ახლა დეაქტივირებულია. გასაგრძელებლად შეიყვანეთ PUK-კოდი. თქვენ დაგრჩათ <xliff:g id="_NUMBER_0">%d</xliff:g> მცდელობა, სანამ SIM სამუდამოდ გამოუსადეგარი გახდება. დეტალური ინფორმაციისთვის დაუკავშირდით თქვენს ოპერატორს.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml index 4b0a7ff743f3..f9e12f115345 100644 --- a/packages/SystemUI/res-keyguard/values-kk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Құрылғы құлпы <xliff:g id="NUMBER_0">%d</xliff:g> сағаттан бері ашылмаған. Құпия сөзді растаңыз.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Анықталмады"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">SIM PIN кодын енгізіңіз. <xliff:g id="NUMBER_1">%d</xliff:g> мүмкіндік қалды.</item> + <item quantity="one">SIM PIN кодын енгізіңіз. <xliff:g id="NUMBER_0">%d</xliff:g> мүмкіндік қалды, одан кейін оператордан SIM картасының құлпын ашуды сұрауға тура келеді.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM картасы өшірілді. Жалғастыру үшін PUK кодын енгізіңіз. <xliff:g id="_NUMBER_1">%d</xliff:g> мүмкіндік қалды, одан кейін SIM картасы біржола құлыпталады. Толығырақ мәліметті оператордан алыңыз.</item> + <item quantity="one">SIM картасы өшірілді. Жалғастыру үшін PUK кодын енгізіңіз. <xliff:g id="_NUMBER_0">%d</xliff:g> мүмкіндік қалды, одан кейін SIM картасы біржола құлыпталады. Толығырақ мәліметті оператордан алыңыз.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml index 6a48197af535..3bf437992a11 100644 --- a/packages/SystemUI/res-keyguard/values-km/strings.xml +++ b/packages/SystemUI/res-keyguard/values-km/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">ឧបករណ៍បានជាប់សោអស់រយៈពេល <xliff:g id="NUMBER_0">%d</xliff:g> ម៉ោងហើយ។ សូមបញ្ជាក់ពាក្យសម្ងាត់។</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"មិនអាចសម្គាល់បានទេ"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">បញ្ចូលកូដ PIN របស់ស៊ីម អ្នកនៅសល់ការព្យាយាម <xliff:g id="NUMBER_1">%d</xliff:g> ដងទៀត។</item> + <item quantity="one">បញ្ចូលកូដ PIN របស់ស៊ីម អ្នកនៅសល់ការព្យាយាម <xliff:g id="NUMBER_0">%d</xliff:g> ដងទៀត មុនពេលដែលអ្នកត្រូវទាក់ទងទៅក្រុមហ៊ុនសេវាទូរសព្ទរបស់អ្នកដើម្បីដោះសោឧបករណ៍របស់អ្នក។</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">ឥឡូវនេះស៊ីមត្រូវបានបិទ។ សូមបញ្ចូលកូដ PUK ដើម្បីបន្ត។ អ្នកនៅសល់ការព្យាយាម <xliff:g id="_NUMBER_1">%d</xliff:g> ដងទៀតមុនពេលស៊ីមមិនអាចប្រើបានជាអចិន្ត្រៃយ៍។ ទាក់ទងទៅក្រុមហ៊ុនសេវាទូរសព្ទសម្រាប់ព័ត៌មានលម្អិត។</item> + <item quantity="one">ឥឡូវនេះស៊ីមត្រូវបានបិទ។ សូមបញ្ចូលកូដ PUK ដើម្បីបន្ត។ អ្នកនៅសល់ការព្យាយាម <xliff:g id="_NUMBER_0">%d</xliff:g> ដងទៀតមុនពេលស៊ីមមិនអាចប្រើបានជាអចិន្ត្រៃយ៍។ ទាក់ទងទៅក្រុមហ៊ុនសេវាទូរសព្ទសម្រាប់ព័ត៌មានលម្អិត។</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml index 093c5cbc791a..2ee30e9998f1 100644 --- a/packages/SystemUI/res-keyguard/values-kn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml @@ -135,4 +135,6 @@ <item quantity="other">ಸಾಧನವನ್ನು <xliff:g id="NUMBER_1">%d</xliff:g> ಗಂಟೆಗಳವರೆಗೆ ಅನ್ಲಾಕ್ ಮಾಡಿರಲಿಲ್ಲ. ಪಾಸ್ವರ್ಡ್ ಖಚಿತಪಡಿಸಿ.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"ಗುರುತಿಸಲಾಗಿಲ್ಲ"</string> + <!-- no translation found for kg_password_default_pin_message (6203676909479972943) --> + <!-- no translation found for kg_password_default_puk_message (8744416410184198352) --> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml index 9b48a4b1b564..1a34229a01af 100644 --- a/packages/SystemUI/res-keyguard/values-ko/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">기기가 <xliff:g id="NUMBER_0">%d</xliff:g>시간 동안 잠금 해제되지 않았습니다. 비밀번호를 입력하세요.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"인식할 수 없음"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">SIM PIN을 입력하세요. <xliff:g id="NUMBER_1">%d</xliff:g>번 더 시도할 수 있습니다.</item> + <item quantity="one">SIM PIN을 입력하세요. <xliff:g id="NUMBER_0">%d</xliff:g>번 더 실패하면 이동통신사에 문의하여 기기를 잠금 해제해야 합니다.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM이 사용 중지되었습니다. 계속하려면 PUK 코드를 입력하세요. <xliff:g id="_NUMBER_1">%d</xliff:g>번 더 실패하면 SIM을 완전히 사용할 수 없게 됩니다. 자세한 내용은 이동통신사에 문의하세요.</item> + <item quantity="one">SIM이 사용 중지되었습니다. 계속하려면 PUK 코드를 입력하세요. <xliff:g id="_NUMBER_0">%d</xliff:g>번 더 실패하면 SIM을 완전히 사용할 수 없게 됩니다. 자세한 내용은 이동통신사에 문의하세요.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml index d4054e8e8ce2..054ce7c01386 100644 --- a/packages/SystemUI/res-keyguard/values-ky/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Түзмөктүн кулпусу <xliff:g id="NUMBER_0">%d</xliff:g> саат бою ачылган жок. Сырсөздү ырастаңыз.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Таанылган жок"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">SIM-картанын PIN-кодун киргизиңиз, сизде <xliff:g id="NUMBER_1">%d</xliff:g> аракет калды.</item> + <item quantity="one">SIM-картанын PIN-кодун киргизиңиз, сизде <xliff:g id="NUMBER_0">%d</xliff:g> аракет калды. Эми түзмөктү бөгөттөн чыгаруу үчүн байланыш операторуңузга кайрылышыңыз керек.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM-карта азыр жарактан чыкты. Улантуу үчүн PUK-кодду киргизиңиз. SIM-картанын биротоло жарактан чыгарына <xliff:g id="_NUMBER_1">%d</xliff:g> аракет калды. Чоо-жайын билүү үчүн байланыш операторуна кайрылыңыз.</item> + <item quantity="one">SIM-карта азыр жарактан чыкты. Улантуу үчүн PUK-кодду киргизиңиз. SIM-картанын биротоло жарактан чыгарына <xliff:g id="_NUMBER_0">%d</xliff:g> аракет калды. Чоо-жайын билүү үчүн байланыш операторуна кайрылыңыз.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-lo/strings.xml b/packages/SystemUI/res-keyguard/values-lo/strings.xml index e72349bfe9db..545d32a249d1 100644 --- a/packages/SystemUI/res-keyguard/values-lo/strings.xml +++ b/packages/SystemUI/res-keyguard/values-lo/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">ອຸປະກອນບໍ່ໄດ້ຖືກປົດລັອກເປັນເວລາ <xliff:g id="NUMBER_0">%d</xliff:g> ຊົ່ວໂມງ. ຢືນຢັນລະຫັດຜ່ານ.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"ບໍ່ຮັບຮູ້"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">ລະຫັດ PIN ຂອງ SIM ບໍ່ຖືກຕ້ອງ, ທ່ານສາມາດລອງໄດ້ອີກ <xliff:g id="NUMBER_1">%d</xliff:g> ເທື່ອ.</item> + <item quantity="one">ລະຫັດ PIN ຂອງ SIM ບໍ່ຖືກຕ້ອງ, ທ່ານສາມາດລອງໄດ້ອີກ <xliff:g id="NUMBER_0">%d</xliff:g> ເທື່ອກ່ອນທີ່ທ່ານຈະຕ້ອງຕິດຕໍ່ຫາຜູ້ໃຫ້ບໍລິການຂອງທ່ານເພື່ອປົດລັອກອຸປະກອນທ່ານ.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">ຕອນນີ້ປິດການນຳໃຊ້ SIM ແລ້ວ. ໃສ່ລະຫັດ PUK ເພື່ອດຳເນີນການຕໍ່. ທ່ານສາມາດລອງໄດ້ອີກ <xliff:g id="_NUMBER_1">%d</xliff:g> ເທື່ອກ່ອນທີ່ SIM ຈະບໍ່ສາມາດໃຊ້ໄດ້ຖາວອນ. ກະລຸນາຕິດຕໍ່ຜູ້ໃຫ້ບໍລິການສຳລັບລາຍລະອຽດ.</item> + <item quantity="one">ຕອນນີ້ປິດການນຳໃຊ້ SIM ແລ້ວ. ໃສ່ລະຫັດ PUK ເພື່ອດຳເນີນການຕໍ່. ທ່ານສາມາດລອງໄດ້ອີກ <xliff:g id="_NUMBER_0">%d</xliff:g> ເທື່ອກ່ອນທີ່ SIM ຈະບໍ່ສາມາດໃຊ້ໄດ້ຖາວອນ. ກະລຸນາຕິດຕໍ່ຜູ້ໃຫ້ບໍລິການສຳລັບລາຍລະອຽດ.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-lt/strings.xml b/packages/SystemUI/res-keyguard/values-lt/strings.xml index 0f51f00f8d84..bf041a0912ef 100644 --- a/packages/SystemUI/res-keyguard/values-lt/strings.xml +++ b/packages/SystemUI/res-keyguard/values-lt/strings.xml @@ -147,4 +147,16 @@ <item quantity="other">Įrenginys nebuvo atrakintas <xliff:g id="NUMBER_1">%d</xliff:g> valandų. Patvirtinkite slaptažodį.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Neatpažinta"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Įveskite SIM kortelės PIN kodą. Jums liko <xliff:g id="NUMBER_1">%d</xliff:g> bandymas.</item> + <item quantity="few">Įveskite SIM kortelės PIN kodą. Jums liko <xliff:g id="NUMBER_1">%d</xliff:g> bandymai.</item> + <item quantity="many">Įveskite SIM kortelės PIN kodą. Jums liko <xliff:g id="NUMBER_1">%d</xliff:g> bandymo.</item> + <item quantity="other">Įveskite SIM kortelės PIN kodą. Jums liko <xliff:g id="NUMBER_1">%d</xliff:g> bandymų.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">SIM kortelė dabar yra išjungta. Jei norite tęsti, įveskite PUK kodą. Jums liko <xliff:g id="_NUMBER_1">%d</xliff:g> bandymas. Paskui visiškai nebegalėsite naudoti SIM kortelės. Jei reikia išsamios informacijos, susisiekite su operatoriumi.</item> + <item quantity="few">SIM kortelė dabar yra išjungta. Jei norite tęsti, įveskite PUK kodą. Jums liko <xliff:g id="_NUMBER_1">%d</xliff:g> bandymai. Paskui visiškai nebegalėsite naudoti SIM kortelės. Jei reikia išsamios informacijos, susisiekite su operatoriumi.</item> + <item quantity="many">SIM kortelė dabar yra išjungta. Jei norite tęsti, įveskite PUK kodą. Jums liko <xliff:g id="_NUMBER_1">%d</xliff:g> bandymo. Paskui visiškai nebegalėsite naudoti SIM kortelės. Jei reikia išsamios informacijos, susisiekite su operatoriumi.</item> + <item quantity="other">SIM kortelė dabar yra išjungta. Jei norite tęsti, įveskite PUK kodą. Jums liko <xliff:g id="_NUMBER_1">%d</xliff:g> bandymų. Paskui visiškai nebegalėsite naudoti SIM kortelės. Jei reikia išsamios informacijos, susisiekite su operatoriumi.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-lv/strings.xml b/packages/SystemUI/res-keyguard/values-lv/strings.xml index bdd5dd54cb00..475e9ce56fbe 100644 --- a/packages/SystemUI/res-keyguard/values-lv/strings.xml +++ b/packages/SystemUI/res-keyguard/values-lv/strings.xml @@ -141,4 +141,14 @@ <item quantity="other">Ierīce nav tikusi atbloķēta <xliff:g id="NUMBER_1">%d</xliff:g> stundas. Apstipriniet paroli.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Nav atpazīts"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="zero">Ievadiet SIM kartes PIN kodu. Varat mēģināt vēl <xliff:g id="NUMBER_1">%d</xliff:g> reizes.</item> + <item quantity="one">Ievadiet SIM kartes PIN kodu. Varat mēģināt vēl <xliff:g id="NUMBER_1">%d</xliff:g> reizi.</item> + <item quantity="other">Ievadiet SIM kartes PIN kodu. Varat mēģināt vēl <xliff:g id="NUMBER_1">%d</xliff:g> reizes.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="zero">SIM karte tagad ir atspējota. Ievadiet PUK kodu, lai turpinātu. Varat mēģināt vēl <xliff:g id="_NUMBER_1">%d</xliff:g> reizes. Kļūdas gadījumā SIM karti vairs nevarēs izmantot. Lai iegūtu detalizētu informāciju, sazinieties ar mobilo sakaru operatoru.</item> + <item quantity="one">SIM karte tagad ir atspējota. Ievadiet PUK kodu, lai turpinātu. Varat mēģināt vēl <xliff:g id="_NUMBER_1">%d</xliff:g> reizi. Kļūdas gadījumā SIM karti vairs nevarēs izmantot. Lai iegūtu detalizētu informāciju, sazinieties ar mobilo sakaru operatoru.</item> + <item quantity="other">SIM karte tagad ir atspējota. Ievadiet PUK kodu, lai turpinātu. Varat mēģināt vēl <xliff:g id="_NUMBER_1">%d</xliff:g> reizes. Kļūdas gadījumā SIM karti vairs nevarēs izmantot. Lai iegūtu detalizētu informāciju, sazinieties ar mobilo sakaru operatoru.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml index e14989f08733..095178739d66 100644 --- a/packages/SystemUI/res-keyguard/values-mk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml @@ -135,4 +135,12 @@ <item quantity="other">Уредот не е отклучен веќе <xliff:g id="NUMBER_1">%d</xliff:g> часа. Потврдете ја лозинката.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Непознат"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Внесете PIN-код за SIM-картичката. Ви преостанува уште <xliff:g id="NUMBER_1">%d</xliff:g> обид.</item> + <item quantity="other">Внесете PIN-код за SIM-картичката. Ви преостануваат уште <xliff:g id="NUMBER_1">%d</xliff:g> обиди.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">SIM-картичката сега е оневозможена. Внесете PUK-код за да продолжите. Ви преостанува уште <xliff:g id="_NUMBER_1">%d</xliff:g> обид пред SIM-картичката да стане трајно неупотреблива. Контактирајте го операторот за детали.</item> + <item quantity="other">SIM-картичката сега е оневозможена. Внесете PUK-код за да продолжите. Ви преостануваат уште <xliff:g id="_NUMBER_1">%d</xliff:g> обиди пред SIM-картичката да стане трајно неупотреблива. Контактирајте го операторот за детали.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml index 0b2123189559..7f0e9578e816 100644 --- a/packages/SystemUI/res-keyguard/values-ml/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ml/strings.xml @@ -135,4 +135,6 @@ <item quantity="one">ഉപകരണം <xliff:g id="NUMBER_0">%d</xliff:g> മണിക്കൂറായി അൺലോക്ക് ചെയ്തിട്ടില്ല. പാസ്വേഡ് സ്ഥിരീകരിക്കുക.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"തിരിച്ചറിഞ്ഞില്ല"</string> + <!-- no translation found for kg_password_default_pin_message (6203676909479972943) --> + <!-- no translation found for kg_password_default_puk_message (8744416410184198352) --> </resources> diff --git a/packages/SystemUI/res-keyguard/values-mn/strings.xml b/packages/SystemUI/res-keyguard/values-mn/strings.xml index c8d0b2d6e970..5f9b63d9f76b 100644 --- a/packages/SystemUI/res-keyguard/values-mn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mn/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Төхөөрөмжийн түгжээг <xliff:g id="NUMBER_0">%d</xliff:g> цагийн турш тайлаагүй байна. Нууц үгээ баталгаажуулна уу.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Танигдахгүй байна"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">SIM-н ПИН кодыг оруулна уу. Танд <xliff:g id="NUMBER_1">%d</xliff:g> оролдлого үлдлээ.</item> + <item quantity="one">SIM-н ПИН кодыг оруулна уу. Танд оператор компанитайгаа холбогдохгүйгээр төхөөрөмжийн түгжээг тайлах <xliff:g id="NUMBER_0">%d</xliff:g> оролдлого үлдлээ.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM-г идэвхгүй болголоо. Үргэлжлүүлэхийн тулд PUK кодыг оруулна уу. Таны SIM бүрмөсөн хүчингүй болох хүртэл <xliff:g id="_NUMBER_1">%d</xliff:g> оролдлого үлдлээ. Дэлгэрэнгүй мэдээлэл авахын тулд оператор компанитайгаа холбогдоно уу.</item> + <item quantity="one">SIM-г идэвхгүй болголоо. Үргэлжлүүлэхийн тулд PUK кодыг оруулна уу. Таны SIM бүрмөсөн хүчингүй болох хүртэл <xliff:g id="_NUMBER_0">%d</xliff:g> оролдлого үлдлээ. Дэлгэрэнгүй мэдээлэл авахын тулд оператор компанитайгаа холбогдоно уу.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml index cfda6cc1cd8d..7d04edc8b785 100644 --- a/packages/SystemUI/res-keyguard/values-mr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml @@ -135,4 +135,12 @@ <item quantity="other">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासांसाठी अनलॉक केले गेले नाही. पासवर्डची खात्री करा.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"ओळखले नाही"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">सिम पिन टाका, तुमच्याकडे <xliff:g id="NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहे.</item> + <item quantity="other">सिम पिन टाका, तुमच्याकडे <xliff:g id="NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहेत.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">सिम आता बंद केलेले आहे. सुरू ठेवण्यासाठी PUK कोड टाका. सिम कायमचे बंद होण्याआधी तुमच्याकडे <xliff:g id="_NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहे. तपशीलांसाठी वाहकाशी संपर्क साधा.</item> + <item quantity="other">सिम आता बंद केलेले आहे. सुरू ठेवण्यासाठी PUK कोड टाका. सिम कायमचे बंद होण्याआधी तुमच्याकडे <xliff:g id="_NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहेत. तपशीलांसाठी वाहकाशी संपर्क साधा.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml index 6b8c1e97b069..d37e7ee141e8 100644 --- a/packages/SystemUI/res-keyguard/values-ms/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Peranti tidak dibuka kuncinya selama <xliff:g id="NUMBER_0">%d</xliff:g> jam. Sahkan kata laluan.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Tidak dikenali"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Masukkan PIN SIM, tinggal <xliff:g id="NUMBER_1">%d</xliff:g> percubaan lagi.</item> + <item quantity="one">Masukkan PIN SIM, tinggal <xliff:g id="NUMBER_0">%d</xliff:g> percubaan lagi sebelum anda harus menghubungi pembawa anda untuk membuka kunci peranti.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">Kini SIM dilumpuhkan. Masukkan kod PUK untuk meneruskan. Tinggal <xliff:g id="_NUMBER_1">%d</xliff:g> percubaan sebelum SIM tidak boleh digunakan secara kekal. Hubungi pembawa untuk mendapatkan butiran.</item> + <item quantity="one">Kini SIM dilumpuhkan. Masukkan kod PUK untuk meneruskan. Tinggal <xliff:g id="_NUMBER_0">%d</xliff:g> percubaan sebelum SIM tidak boleh digunakan secara kekal. Hubungi pembawa untuk mendapatkan butiran.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml index 46e8c2e341b5..6534fbb98ad9 100644 --- a/packages/SystemUI/res-keyguard/values-my/strings.xml +++ b/packages/SystemUI/res-keyguard/values-my/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">စက်ပစ္စည်းကို <xliff:g id="NUMBER_0">%d</xliff:g> နာရီကြာ လော့ခ်ဖွင့်ခဲ့ခြင်း မရှိပါ။ စကားဝှက်အား အတည်ပြုပါ။</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"မသိပါ"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">ဆင်းမ်ကဒ် ပင်နံပါတ် ထည့်သွင်းပါ၊ သင့်တွင် <xliff:g id="NUMBER_1">%d</xliff:g> ခါ ကြိုးစားခွင့် ကျန်ပါသေးသည်။</item> + <item quantity="one">ဆင်းမ်ကဒ် ပင်နံပါတ် ထည့်သွင်းပါ၊ သင့်စက်ကို ဖွင့်ရန် ဝန်ဆောင်မှုပေးသူသို့ မဆက်သွယ်မီ သင့်တွင် <xliff:g id="NUMBER_0">%d</xliff:g> ခါ ကြိုးစားခွင့် ကျန်ပါသေးသည်။</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">ဆင်းမ်ကဒ်သည် ယခု ပိတ်သွားပါပြီ။ ရှေ့ဆက်ရန် ပင်နံပါတ် ပြန်ဖွင့်သည့် ကုဒ်ကို ထည့်ပါ။ ဆင်းမ်ကဒ်ကို အပြီးသုံးမရအောင်မပြုမီ သင့်တွင် <xliff:g id="_NUMBER_1">%d</xliff:g> ခါ ကြိုးစားခွင့်ကျန်ပါသေးသည်။ အသေးစိတ်အချက်များအတွက် ဝန်ဆောင်မှုပေးသူကို ဆက်သွယ်ပါ။</item> + <item quantity="one">ဆင်းမ်ကဒ်သည် ယခု ပိတ်သွားပါပြီ။ ရှေ့ဆက်ရန် ပင်နံပါတ် ပြန်ဖွင့်သည့် ကုဒ်ကို ထည့်ပါ။ ဆင်းမ်ကဒ်ကို အပြီးသုံးမရအောင်မပြုမီ သင့်တွင် <xliff:g id="_NUMBER_0">%d</xliff:g> ခါ ကြိုးစားခွင့်ကျန်ပါသေးသည်။ အသေးစိတ်အချက်များအတွက် ဝန်ဆောင်မှုပေးသူကို ဆက်သွယ်ပါ။</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-nb/strings.xml b/packages/SystemUI/res-keyguard/values-nb/strings.xml index b2063956f187..ca51c968b410 100644 --- a/packages/SystemUI/res-keyguard/values-nb/strings.xml +++ b/packages/SystemUI/res-keyguard/values-nb/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Enheten har ikke blitt låst opp på <xliff:g id="NUMBER_0">%d</xliff:g> time. Bekreft passordet.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Ikke gjenkjent"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Skriv inn PIN-koden for SIM-kortet. Du har <xliff:g id="NUMBER_1">%d</xliff:g> forsøk igjen.</item> + <item quantity="one">Skriv inn PIN-koden for SIM-kortet. Du har <xliff:g id="NUMBER_0">%d</xliff:g> forsøk igjen før du må kontakte operatøren din for å låse opp enheten.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM-kortet er deaktivert nå. Skriv inn PUK-koden for å fortsette. Du har <xliff:g id="_NUMBER_1">%d</xliff:g> forsøk igjen før SIM-kortet blir permanent ubrukelig. Kontakt operatøren for å få vite mer.</item> + <item quantity="one">SIM-kortet er deaktivert nå. Skriv inn PUK-koden for å fortsette. Du har <xliff:g id="_NUMBER_0">%d</xliff:g> forsøk igjen før SIM-kortet blir permanent ubrukelig. Kontakt operatøren for å få vite mer.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml index d5ac1d84212f..90d6c5cfc00c 100644 --- a/packages/SystemUI/res-keyguard/values-ne/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">यन्त्र <xliff:g id="NUMBER_0">%d</xliff:g> घन्टा देखि अनलक भएको छैन। पासवर्ड पुष्टि गर्नुहोस्।</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"पहिचान भएन"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">SIM को PIN प्रविष्ट गर्नुहोस् तपाईंसँग <xliff:g id="NUMBER_1">%d</xliff:g> प्रयासहरू बाँकी छन्।</item> + <item quantity="one">SIM को PIN प्रविष्ट गर्नुहोस्, तपाईंसँग <xliff:g id="NUMBER_0">%d</xliff:g> प्रयास बाँकी छ, त्यसपछि भने आफ्नो यन्त्र अनलक गर्नका लागि तपाईंले अनिवार्य रूपमा आफ्नो सेवा प्रदायकलाई सम्पर्क गर्नपर्ने हुन्छ।</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM लाई असक्षम पारिएको छ। जारी राख्न PUK कोड प्रविष्ट गर्नुहोस्। तपाईंसँग <xliff:g id="_NUMBER_1">%d</xliff:g> प्रयासहरू बाँकी छन्, त्यसपछि SIM सदाका लागि प्रयोग गर्न नमिल्ने हुन्छ। विवरणहरूका लागि सेवा प्रदायकलाई सम्पर्क गर्नुहोस्।</item> + <item quantity="one">SIM लाई असक्षम पारिएको छ। जारी राख्न PUK कोड प्रविष्ट गर्नुहोस्। तपाईंसँग <xliff:g id="_NUMBER_0">%d</xliff:g> प्रयास बाँकी छ, त्यसपछि SIM सदाका लागि प्रयोग गर्न नमिल्ने हुन्छ। विवरणहरूका लागि सेवा प्रदायकलाई सम्पर्क गर्नुहोस्।</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml index 6a1f3c92cd1a..85e0a95d3994 100644 --- a/packages/SystemUI/res-keyguard/values-nl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Apparaat is al <xliff:g id="NUMBER_0">%d</xliff:g> uur niet ontgrendeld. Bevestig het wachtwoord.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Niet herkend"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Geef de pincode van de simkaart op. Je hebt nog <xliff:g id="NUMBER_1">%d</xliff:g> pogingen over.</item> + <item quantity="one">Geef de pincode van de simkaart op. Je hebt nog <xliff:g id="NUMBER_0">%d</xliff:g> poging over voordat je contact met je provider moet opnemen om het apparaat te ontgrendelen.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">De simkaart is nu uitgeschakeld. Geef de pukcode op om door te gaan. Je hebt nog <xliff:g id="_NUMBER_1">%d</xliff:g> pogingen over voordat de simkaart definitief onbruikbaar wordt. Neem contact op met je provider voor meer informatie.</item> + <item quantity="one">De simkaart is nu uitgeschakeld. Geef de pukcode op om door te gaan. Je hebt nog <xliff:g id="_NUMBER_0">%d</xliff:g> poging over voordat de simkaart definitief onbruikbaar wordt. Neem contact op met je provider voor meer informatie.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml index 0bab97dd1959..dc0e53bae184 100644 --- a/packages/SystemUI/res-keyguard/values-pa/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml @@ -135,4 +135,6 @@ <item quantity="other">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟਿਆਂ ਤੋਂ ਅਣਲਾਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪਾਸਵਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string> + <!-- no translation found for kg_password_default_pin_message (6203676909479972943) --> + <!-- no translation found for kg_password_default_puk_message (8744416410184198352) --> </resources> diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml index 59f441290208..ee6ad623a742 100644 --- a/packages/SystemUI/res-keyguard/values-pl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml @@ -147,4 +147,16 @@ <item quantity="one">Urządzenie nie zostało odblokowane od <xliff:g id="NUMBER_0">%d</xliff:g> godziny. Potwierdź hasło.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Nie rozpoznano"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="few">Wpisz kod PIN karty SIM. Masz jeszcze <xliff:g id="NUMBER_1">%d</xliff:g> próby.</item> + <item quantity="many">Wpisz kod PIN karty SIM. Masz jeszcze <xliff:g id="NUMBER_1">%d</xliff:g> prób.</item> + <item quantity="other">Wpisz kod PIN karty SIM. Masz jeszcze <xliff:g id="NUMBER_1">%d</xliff:g> próby.</item> + <item quantity="one">Wpisz kod PIN karty SIM. Masz jeszcze <xliff:g id="NUMBER_0">%d</xliff:g> próbę, zanim będzie trzeba skontaktować się z operatorem, by odblokować to urządzenie.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="few">Karta SIM została wyłączona. Wpisz kod PUK, by przejść dalej. Masz jeszcze <xliff:g id="_NUMBER_1">%d</xliff:g> próby, zanim karta SIM zostanie trwale zablokowana. Aby uzyskać szczegółowe informacje, skontaktuj się z operatorem.</item> + <item quantity="many">Karta SIM została wyłączona. Wpisz kod PUK, by przejść dalej. Masz jeszcze <xliff:g id="_NUMBER_1">%d</xliff:g> prób, zanim karta SIM zostanie trwale zablokowana. Aby uzyskać szczegółowe informacje, skontaktuj się z operatorem.</item> + <item quantity="other">Karta SIM została wyłączona. Wpisz kod PUK, by przejść dalej. Masz jeszcze <xliff:g id="_NUMBER_1">%d</xliff:g> próby, zanim karta SIM zostanie trwale zablokowana. Aby uzyskać szczegółowe informacje, skontaktuj się z operatorem.</item> + <item quantity="one">Karta SIM została wyłączona. Wpisz kod PUK, by przejść dalej. Masz jeszcze <xliff:g id="_NUMBER_0">%d</xliff:g> próbę, zanim karta SIM zostanie trwale zablokowana. Aby uzyskać szczegółowe informacje, skontaktuj się z operatorem.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml index 362ffcf70852..bb547f157185 100644 --- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml @@ -135,4 +135,12 @@ <item quantity="other">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirme a senha.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Não reconhecido"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Informe o PIN do SIM. Você tem <xliff:g id="NUMBER_1">%d</xliff:g> tentativa restante.</item> + <item quantity="other">Informe o PIN do SIM. Você tem <xliff:g id="NUMBER_1">%d</xliff:g> tentativas restantes.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">O SIM agora está desativado. Informe o código PUK para continuar. Você tem <xliff:g id="_NUMBER_1">%d</xliff:g> tentativa restante antes de o SIM se tornar permanentemente inutilizável. Entre em contato com a operadora para saber mais detalhes.</item> + <item quantity="other">O SIM agora está desativado. Informe o código PUK para continuar. Você tem <xliff:g id="_NUMBER_1">%d</xliff:g> tentativas restantes antes de o SIM se tornar permanentemente inutilizável. Entre em contato com a operadora para saber mais detalhes.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml index 70d13e67145f..6a0e6274b161 100644 --- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirme a palavra-passe.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Não reconhecido"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Introduza o PIN do cartão SIM. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas.</item> + <item quantity="one">Introduza o PIN do cartão SIM. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de ser necessário contactar o operador para desbloquear o dispositivo.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">O SIM encontra-se desativado. Introduza o código PUK para continuar. Tem mais <xliff:g id="_NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.</item> + <item quantity="one">O SIM encontra-se desativado. Introduza o código PUK para continuar. Tem mais <xliff:g id="_NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml index 362ffcf70852..bb547f157185 100644 --- a/packages/SystemUI/res-keyguard/values-pt/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml @@ -135,4 +135,12 @@ <item quantity="other">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirme a senha.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Não reconhecido"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Informe o PIN do SIM. Você tem <xliff:g id="NUMBER_1">%d</xliff:g> tentativa restante.</item> + <item quantity="other">Informe o PIN do SIM. Você tem <xliff:g id="NUMBER_1">%d</xliff:g> tentativas restantes.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">O SIM agora está desativado. Informe o código PUK para continuar. Você tem <xliff:g id="_NUMBER_1">%d</xliff:g> tentativa restante antes de o SIM se tornar permanentemente inutilizável. Entre em contato com a operadora para saber mais detalhes.</item> + <item quantity="other">O SIM agora está desativado. Informe o código PUK para continuar. Você tem <xliff:g id="_NUMBER_1">%d</xliff:g> tentativas restantes antes de o SIM se tornar permanentemente inutilizável. Entre em contato com a operadora para saber mais detalhes.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ro/strings.xml b/packages/SystemUI/res-keyguard/values-ro/strings.xml index d0dc17e567a6..341c95297733 100644 --- a/packages/SystemUI/res-keyguard/values-ro/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ro/strings.xml @@ -141,4 +141,14 @@ <item quantity="one">Dispozitivul nu a fost deblocat de <xliff:g id="NUMBER_0">%d</xliff:g> oră. Confirmați parola.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Nu este recunoscută"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="few">Introduceți codul PIN pentru cardul SIM. V-au mai rămas <xliff:g id="NUMBER_1">%d</xliff:g> încercări.</item> + <item quantity="other">Introduceți codul PIN pentru cardul SIM. V-au mai rămas <xliff:g id="NUMBER_1">%d</xliff:g> de încercări.</item> + <item quantity="one">Introduceți codul PIN pentru cardul SIM. V-a mai rămas <xliff:g id="NUMBER_0">%d</xliff:g> încercare, după care va trebui să contactați operatorul pentru a vă debloca dispozitivul.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="few">Cardul SIM este dezactivat acum. Introduceți codul PUK pentru a continua. V-au mai rămas <xliff:g id="_NUMBER_1">%d</xliff:g> încercări până când cardul SIM va deveni inutilizabil definitiv. Contactați operatorul pentru detalii.</item> + <item quantity="other">Cardul SIM este dezactivat acum. Introduceți codul PUK pentru a continua. V-au mai rămas <xliff:g id="_NUMBER_1">%d</xliff:g> de încercări până când cardul SIM va deveni inutilizabil definitiv. Contactați operatorul pentru detalii.</item> + <item quantity="one">Cardul SIM este dezactivat acum. Introduceți codul PUK pentru a continua. V-a mai rămas <xliff:g id="_NUMBER_0">%d</xliff:g> încercare până când cardul SIM va deveni inutilizabil definitiv. Contactați operatorul pentru detalii.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml index f629957f0bc0..1a794ee0a7b4 100644 --- a/packages/SystemUI/res-keyguard/values-ru/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml @@ -147,4 +147,16 @@ <item quantity="other">Устройство не разблокировалось в течение <xliff:g id="NUMBER_1">%d</xliff:g> часа. Введите пароль ещё раз.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Не распознано"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Неверный PIN-код. Осталась <xliff:g id="NUMBER_1">%d</xliff:g> попытка.</item> + <item quantity="few">Неверный PIN-код. Осталось <xliff:g id="NUMBER_1">%d</xliff:g> попытки.</item> + <item quantity="many">Неверный PIN-код. Осталось <xliff:g id="NUMBER_1">%d</xliff:g> попыток.</item> + <item quantity="other">Неверный PIN-код. Осталось <xliff:g id="NUMBER_1">%d</xliff:g> попытки.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">SIM-карта отключена. Чтобы продолжить, введите PUK-код. Осталась <xliff:g id="_NUMBER_1">%d</xliff:g> попытка. После этого SIM-карта будет заблокирована навсегда. За подробной информацией обратитесь к оператору связи.</item> + <item quantity="few">SIM-карта отключена. Чтобы продолжить, введите PUK-код. Осталось <xliff:g id="_NUMBER_1">%d</xliff:g> попытки. После этого SIM-карта будет заблокирована навсегда. За подробной информацией обратитесь к оператору связи.</item> + <item quantity="many">SIM-карта отключена. Чтобы продолжить, введите PUK-код. Осталось <xliff:g id="_NUMBER_1">%d</xliff:g> попыток. После этого SIM-карта будет заблокирована навсегда. За подробной информацией обратитесь к оператору связи.</item> + <item quantity="other">SIM-карта отключена. Чтобы продолжить, введите PUK-код. Осталось <xliff:g id="_NUMBER_1">%d</xliff:g> попытки. После этого SIM-карта будет заблокирована навсегда. За подробной информацией обратитесь к оператору связи.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-si/strings.xml b/packages/SystemUI/res-keyguard/values-si/strings.xml index 4981855325cd..d36e7520b6ad 100644 --- a/packages/SystemUI/res-keyguard/values-si/strings.xml +++ b/packages/SystemUI/res-keyguard/values-si/strings.xml @@ -135,4 +135,12 @@ <item quantity="other">උපාංගය පැය <xliff:g id="NUMBER_1">%d</xliff:g>ක් අගුලු හැර නැත. මුරපදය තහවුරු කරන්න.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"හඳුනා නොගන්නා ලදී"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">SIM PIN ඇතුළු කරන්න, ඔබ සතුව උත්සාහයන් <xliff:g id="NUMBER_1">%d</xliff:g>ක් ඉතිරිව ඇත.</item> + <item quantity="other">SIM PIN ඇතුළු කරන්න, ඔබ සතුව උත්සාහයන් <xliff:g id="NUMBER_1">%d</xliff:g>ක් ඉතිරිව ඇත.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">SIM දැන් අබල කර ඇත. දිගටම කරගෙන යාමට PUK කේතය ඇතුළු කරන්න. SIM ස්ථිරවම භාවිත කළ නොහැකි බවට පත් වීමට පෙර ඔබ සතුව උත්සාහයන් <xliff:g id="_NUMBER_1">%d</xliff:g>ක් ඉතිරිව ඇත. විස්තර සඳහා වාහක සම්බන්ධ කර ගන්න.</item> + <item quantity="other">SIM දැන් අබල කර ඇත. දිගටම කරගෙන යාමට PUK කේතය ඇතුළු කරන්න. SIM ස්ථිරවම භාවිත කළ නොහැකි බවට පත් වීමට පෙර ඔබ සතුව උත්සාහයන් <xliff:g id="_NUMBER_1">%d</xliff:g>ක් ඉතිරිව ඇත. විස්තර සඳහා වාහක සම්බන්ධ කර ගන්න.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-sk/strings.xml b/packages/SystemUI/res-keyguard/values-sk/strings.xml index 99007eedc2ce..b69f50241b89 100644 --- a/packages/SystemUI/res-keyguard/values-sk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sk/strings.xml @@ -147,4 +147,16 @@ <item quantity="one">Zariadenie nebolo odomknuté <xliff:g id="NUMBER_0">%d</xliff:g> hodinu. Potvrďte heslo.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Nerozpoznané"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="few">Zadajte kód PIN SIM karty. Zostávajú vám <xliff:g id="NUMBER_1">%d</xliff:g> pokusy.</item> + <item quantity="many">Zadajte kód PIN SIM karty. Zostáva vám <xliff:g id="NUMBER_1">%d</xliff:g> pokusu.</item> + <item quantity="other">Zadajte kód PIN SIM karty. Zostáva vám <xliff:g id="NUMBER_1">%d</xliff:g> pokusov.</item> + <item quantity="one">Zadajte kód PIN SIM karty. Zostáva vám <xliff:g id="NUMBER_0">%d</xliff:g> pokus, potom budete musieť kontaktovať svojho operátora, aby odomkol zariadenie.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="few">SIM karta je deaktivovaná. Pokračujte zadaním kódu PUK. Zostávajú vám <xliff:g id="_NUMBER_1">%d</xliff:g> pokusy, potom sa SIM karta natrvalo zablokuje. Podrobnosti vám poskytne operátor.</item> + <item quantity="many">SIM karta je deaktivovaná. Pokračujte zadaním kódu PUK. Zostáva vám <xliff:g id="_NUMBER_1">%d</xliff:g> pokusu, potom sa SIM karta natrvalo zablokuje. Podrobnosti vám poskytne operátor.</item> + <item quantity="other">SIM karta je deaktivovaná. Pokračujte zadaním kódu PUK. Zostáva vám <xliff:g id="_NUMBER_1">%d</xliff:g> pokusov, potom sa SIM karta natrvalo zablokuje. Podrobnosti vám poskytne operátor.</item> + <item quantity="one">SIM karta je deaktivovaná. Pokračujte zadaním kódu PUK. Zostáva vám <xliff:g id="_NUMBER_0">%d</xliff:g> pokus, potom sa SIM karta natrvalo zablokuje. Podrobnosti vám poskytne operátor.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-sl/strings.xml b/packages/SystemUI/res-keyguard/values-sl/strings.xml index 2a087650e944..cd53c6c67eed 100644 --- a/packages/SystemUI/res-keyguard/values-sl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sl/strings.xml @@ -147,4 +147,16 @@ <item quantity="other">Naprava ni bila odklenjena <xliff:g id="NUMBER_1">%d</xliff:g> ur. Potrdite geslo.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Ni prepoznano"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Vnesite kodo PIN kartice SIM. Na voljo imate še <xliff:g id="NUMBER_1">%d</xliff:g> poskus.</item> + <item quantity="two">Vnesite kodo PIN kartice SIM. Na voljo imate še <xliff:g id="NUMBER_1">%d</xliff:g> poskusa.</item> + <item quantity="few">Vnesite kodo PIN kartice SIM. Na voljo imate še <xliff:g id="NUMBER_1">%d</xliff:g> poskuse.</item> + <item quantity="other">Vnesite kodo PIN kartice SIM. Na voljo imate še <xliff:g id="NUMBER_1">%d</xliff:g> poskusov.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">Kartica SIM je zdaj onemogočena. Če želite nadaljevati, vnesite kodo PUK. Na voljo imate še <xliff:g id="_NUMBER_1">%d</xliff:g> poskus. Potem bo kartica SIM postala trajno neuporabna. Za podrobnosti se obrnite na operaterja.</item> + <item quantity="two">Kartica SIM je zdaj onemogočena. Če želite nadaljevati, vnesite kodo PUK. Na voljo imate še <xliff:g id="_NUMBER_1">%d</xliff:g> poskusa. Potem bo kartica SIM postala trajno neuporabna. Za podrobnosti se obrnite na operaterja.</item> + <item quantity="few">Kartica SIM je zdaj onemogočena. Če želite nadaljevati, vnesite kodo PUK. Na voljo imate še <xliff:g id="_NUMBER_1">%d</xliff:g> poskuse. Potem bo kartica SIM postala trajno neuporabna. Za podrobnosti se obrnite na operaterja.</item> + <item quantity="other">Kartica SIM je zdaj onemogočena. Če želite nadaljevati, vnesite kodo PUK. Na voljo imate še <xliff:g id="_NUMBER_1">%d</xliff:g> poskusov. Potem bo kartica SIM postala trajno neuporabna. Za podrobnosti se obrnite na operaterja.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml index fd52d3951d45..0a55795d0b5e 100644 --- a/packages/SystemUI/res-keyguard/values-sq/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Pajisja nuk është shkyçur për <xliff:g id="NUMBER_0">%d</xliff:g> orë. Konfirmo fjalëkalimin.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Nuk njihet"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Fut kodin PIN të kartës SIM, të kanë mbetur edhe <xliff:g id="NUMBER_1">%d</xliff:g> tentativa.</item> + <item quantity="one">Fut kodin PIN të kartës SIM, të ka mbetur edhe <xliff:g id="NUMBER_0">%d</xliff:g> tentativë para se të kontaktosh me operatorin tënd celular për ta shkyçur pajisjen.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">Karta SIM tani është çaktivizuar. Fut kodin PUK për të vazhduar. Të kanë mbetur edhe <xliff:g id="_NUMBER_1">%d</xliff:g> përpjekje përpara se karta SIM të bëhet përgjithmonë e papërdorshme. Kontakto me operatorin për detaje.</item> + <item quantity="one">Karta SIM tani është çaktivizuar. Fut kodin PUK për të vazhduar. Të ka mbetur edhe <xliff:g id="_NUMBER_0">%d</xliff:g> përpjekje përpara se karta SIM të bëhet përgjithmonë e papërdorshme. Kontakto me operatorin për detaje.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-sr/strings.xml b/packages/SystemUI/res-keyguard/values-sr/strings.xml index 9d06e008f7c5..08db0bd14844 100644 --- a/packages/SystemUI/res-keyguard/values-sr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sr/strings.xml @@ -141,4 +141,14 @@ <item quantity="other">Нисте откључали уређај <xliff:g id="NUMBER_1">%d</xliff:g> сати. Потврдите лозинку.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Није препознат"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Унесите PIN за SIM. Имате још <xliff:g id="NUMBER_1">%d</xliff:g> покушај.</item> + <item quantity="few">Унесите PIN за SIM. Имате још <xliff:g id="NUMBER_1">%d</xliff:g> покушаја.</item> + <item quantity="other">Унесите PIN за SIM. Имате још <xliff:g id="NUMBER_1">%d</xliff:g> покушаја.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">SIM је сада онемогућен. Унесите PUK кôд да бисте наставили. Имате још <xliff:g id="_NUMBER_1">%d</xliff:g> покушај пре него што SIM постане трајно неупотребљив. Детаљне информације потражите од мобилног оператера.</item> + <item quantity="few">SIM је сада онемогућен. Унесите PUK кôд да бисте наставили. Имате још <xliff:g id="_NUMBER_1">%d</xliff:g> покушаја пре него што SIM постане трајно неупотребљив. Детаљне информације потражите од мобилног оператера.</item> + <item quantity="other">SIM је сада онемогућен. Унесите PUK кôд да бисте наставили. Имате још <xliff:g id="_NUMBER_1">%d</xliff:g> покушаја пре него што SIM постане трајно неупотребљив. Детаљне информације потражите од мобилног оператера.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-sv/strings.xml b/packages/SystemUI/res-keyguard/values-sv/strings.xml index dc41e0dfe4a3..54a1d0d1feb9 100644 --- a/packages/SystemUI/res-keyguard/values-sv/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sv/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Enheten har inte låsts upp på <xliff:g id="NUMBER_0">%d</xliff:g> timme. Bekräfta lösenordet.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Identifierades inte"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Ange pinkod för SIM-kortet. <xliff:g id="NUMBER_1">%d</xliff:g> försök återstår.</item> + <item quantity="one">Ange pinkod för SIM-kortet. <xliff:g id="NUMBER_0">%d</xliff:g> försök återstår innan du måste kontakta operatören för att låsa upp enheten.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM-kortet är inaktiverat. Ange PUK-koden om du vill fortsätta. <xliff:g id="_NUMBER_1">%d</xliff:g> försök återstår innan SIM-kortet blir obrukbart. Kontakta operatören för mer information.</item> + <item quantity="one">SIM-kortet är inaktiverat. Ange PUK-koden om du vill fortsätta. <xliff:g id="_NUMBER_0">%d</xliff:g> försök återstår innan SIM-kortet blir obrukbart. Kontakta operatören för mer information.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml index ff75819b04cd..7e85131783eb 100644 --- a/packages/SystemUI/res-keyguard/values-sw/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Hujafungua kifaa kwa saa <xliff:g id="NUMBER_0">%d</xliff:g>. Thibitisha nenosiri.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Haikutambua alama ya kidole"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Weka PIN ya SIM, umesalia na majaribio <xliff:g id="NUMBER_1">%d</xliff:g>.</item> + <item quantity="one">PIN ya SIM uliyoweka si sahihi. Umesalia na jaribio <xliff:g id="NUMBER_0">%d</xliff:g> kabla ya kulazimika kuwasiliana na mtoa huduma wako ili afungue kifaa chako.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">Sasa SIM imefungwa. Weka msimbo wa PUK ili uendelee. Umesalia na majaribio <xliff:g id="_NUMBER_1">%d</xliff:g> kabla ya SIM kuacha kufanya kazi kabisa. Wasiliana na mtoa huduma kwa maelezo.</item> + <item quantity="one">Sasa SIM imefungwa. Weka msimbo wa PUK ili uendelee. Umesalia na jaribio <xliff:g id="_NUMBER_0">%d</xliff:g> kabla ya SIM kuacha kufanya kazi kabisa. Wasiliana na mtoa huduma kwa maelezo.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml index 0ba941cd59d4..727ea5beef46 100644 --- a/packages/SystemUI/res-keyguard/values-ta/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml @@ -135,4 +135,6 @@ <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> மணிநேரமாகச் சாதனம் திறக்கப்படவில்லை. கடவுச்சொல்லை உறுதிப்படுத்தவும்.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"அடையாளங்காண முடியவில்லை"</string> + <!-- no translation found for kg_password_default_pin_message (6203676909479972943) --> + <!-- no translation found for kg_password_default_puk_message (8744416410184198352) --> </resources> diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml index 73f709462af4..ddc5928347cc 100644 --- a/packages/SystemUI/res-keyguard/values-te/strings.xml +++ b/packages/SystemUI/res-keyguard/values-te/strings.xml @@ -135,4 +135,6 @@ <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> గంట పాటు పరికరాన్ని అన్లాక్ చేయలేదు. పాస్వర్డ్ని నమోదు చేయండి.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"గుర్తించలేదు"</string> + <!-- no translation found for kg_password_default_pin_message (6203676909479972943) --> + <!-- no translation found for kg_password_default_puk_message (8744416410184198352) --> </resources> diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml index d802f018468a..aa33421b2549 100644 --- a/packages/SystemUI/res-keyguard/values-th/strings.xml +++ b/packages/SystemUI/res-keyguard/values-th/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">ไม่มีการปลดล็อกอุปกรณ์มา <xliff:g id="NUMBER_0">%d</xliff:g> ชั่วโมงแล้ว ยืนยันรหัสผ่าน</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"ไม่รู้จัก"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">ป้อน PIN ของซิม คุณพยายามได้อีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง</item> + <item quantity="one">PIN ของซิมไม่ถูกต้อง คุณพยายามได้อีก <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งก่อนที่จะต้องติดต่อผู้ให้บริการเพื่อปลดล็อกอุปกรณ์</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">ซิมถูกปิดใช้งานในขณะนี้ โปรดป้อนรหัส PUK เพื่อทำต่อ คุณพยายามได้อีก <xliff:g id="_NUMBER_1">%d</xliff:g> ครั้งก่อนที่ซิมจะไม่สามารถใช้งานได้อย่างถาวร โปรดติดต่อสอบถามรายละเอียดจากผู้ให้บริการ</item> + <item quantity="one">ซิมถูกปิดใช้งานในขณะนี้ โปรดป้อนรหัส PUK เพื่อทำต่อ คุณพยายามได้อีก <xliff:g id="_NUMBER_0">%d</xliff:g> ครั้งก่อนที่ซิมจะไม่สามารถใช้งานได้อย่างถาวร โปรดติดต่อสอบถามรายละเอียดจากผู้ให้บริการ</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml index 7e84d2ffe279..30657d4457f9 100644 --- a/packages/SystemUI/res-keyguard/values-tl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml @@ -135,4 +135,12 @@ <item quantity="other">Hindi na-unlock ang device sa loob ng <xliff:g id="NUMBER_1">%d</xliff:g> na oras. Kumpirmahin ang password.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Hindi nakilala"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Ilagay ang PIN ng SIM, mayroon kang <xliff:g id="NUMBER_1">%d</xliff:g> natitirang pagsubok.</item> + <item quantity="other">Ilagay ang PIN ng SIM, mayroon kang <xliff:g id="NUMBER_1">%d</xliff:g> na natitirang pagsubok.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">Naka-disable na ang SIM. Ilagay ang PUK code upang magpatuloy. Mayroon kang <xliff:g id="_NUMBER_1">%d</xliff:g> natitirang pagsubok bago tuluyang hindi magamit ang SIM. Makipag-ugnayan sa carrier para sa mga detalye.</item> + <item quantity="other">Naka-disable na ang SIM. Ilagay ang PUK code upang magpatuloy. Mayroon kang <xliff:g id="_NUMBER_1">%d</xliff:g> na natitirang pagsubok bago tuluyang hindi magamit ang SIM. Makipag-ugnayan sa carrier para sa mga detalye.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-tr/strings.xml b/packages/SystemUI/res-keyguard/values-tr/strings.xml index b80e4db816ce..ca53dfb8fd69 100644 --- a/packages/SystemUI/res-keyguard/values-tr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-tr/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Cihazın kilidi son <xliff:g id="NUMBER_0">%d</xliff:g> saattir açılmadı. Şifreyi doğrulayın.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Tanınmadı"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">SIM PIN\'inizi girin. <xliff:g id="NUMBER_1">%d</xliff:g> deneme hakkınız kaldı.</item> + <item quantity="one">SIM PIN\'inizi girin. Cihazınızın kilidini açmak için operatörünüzle bağlantı kurmak zorunda kalmadan önce <xliff:g id="NUMBER_0">%d</xliff:g> deneme hakkınız kaldı.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM artık devre dışı. Devam etmek için PUK kodunu girin. SIM kalıcı olarak kullanım dışı kalmadan önce <xliff:g id="_NUMBER_1">%d</xliff:g> deneme hakkınız kaldı. Ayrıntılı bilgi için operatörünüzle iletişim kurun.</item> + <item quantity="one">SIM artık devre dışı. Devam etmek için PUK kodunu girin. SIM kalıcı olarak kullanım dışı kalmadan önce <xliff:g id="_NUMBER_0">%d</xliff:g> deneme hakkınız kaldı. Ayrıntılı bilgi için operatörünüzle iletişim kurun.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-uk/strings.xml b/packages/SystemUI/res-keyguard/values-uk/strings.xml index f25928abeefe..4b79744573d6 100644 --- a/packages/SystemUI/res-keyguard/values-uk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-uk/strings.xml @@ -147,4 +147,16 @@ <item quantity="other">Ви не розблоковували пристрій <xliff:g id="NUMBER_1">%d</xliff:g> години. Підтвердьте пароль.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Не розпізнано"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Введіть PIN-код SIM-карти. Залишилася <xliff:g id="NUMBER_1">%d</xliff:g> спроба.</item> + <item quantity="few">Введіть PIN-код SIM-карти. Залишилося <xliff:g id="NUMBER_1">%d</xliff:g> спроби.</item> + <item quantity="many">Введіть PIN-код SIM-карти. Залишилося <xliff:g id="NUMBER_1">%d</xliff:g> спроб.</item> + <item quantity="other">Введіть PIN-код SIM-карти. Залишилося <xliff:g id="NUMBER_1">%d</xliff:g> спроби.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">SIM-карту заблоковано. Щоб продовжити, введіть PUK-код. Залишилася <xliff:g id="_NUMBER_1">%d</xliff:g> спроба. Після цього SIM-карту буде назавжди заблоковано. Щоб дізнатися більше, зверніться до свого оператора.</item> + <item quantity="few">SIM-карту заблоковано. Щоб продовжити, введіть PUK-код. Залишилося <xliff:g id="_NUMBER_1">%d</xliff:g> спроби. Після цього SIM-карту буде назавжди заблоковано. Щоб дізнатися більше, зверніться до свого оператора.</item> + <item quantity="many">SIM-карту заблоковано. Щоб продовжити, введіть PUK-код. Залишилося <xliff:g id="_NUMBER_1">%d</xliff:g> спроб. Після цього SIM-карту буде назавжди заблоковано. Щоб дізнатися більше, зверніться до свого оператора.</item> + <item quantity="other">SIM-карту заблоковано. Щоб продовжити, введіть PUK-код. Залишилося <xliff:g id="_NUMBER_1">%d</xliff:g> спроби. Після цього SIM-карту буде назавжди заблоковано. Щоб дізнатися більше, зверніться до свого оператора.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml index 3bb59f01aa61..5440a87ff22f 100644 --- a/packages/SystemUI/res-keyguard/values-ur/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml @@ -135,4 +135,6 @@ <item quantity="one">آلہ <xliff:g id="NUMBER_0">%d</xliff:g> گھنٹہ سے غیر مقفل نہیں کیا گیا۔ پاسورڈ کی توثیق کریں۔</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"تسلیم شدہ نہیں ہے"</string> + <!-- no translation found for kg_password_default_pin_message (6203676909479972943) --> + <!-- no translation found for kg_password_default_puk_message (8744416410184198352) --> </resources> diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml index 699ad6002760..ee11cffd09d2 100644 --- a/packages/SystemUI/res-keyguard/values-uz/strings.xml +++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Qurilma <xliff:g id="NUMBER_0">%d</xliff:g> soatdan beri qulfdan chiqarilgani yo‘q. Parolni yana bir marta kiriting.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Barmoq izi aniqlanmadi"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">SIM PIN kodini kiriting, sizda <xliff:g id="NUMBER_1">%d</xliff:g> ta urinish bor.</item> + <item quantity="one">SIM PIN kodini kiriting, qurilmani qulfdan chiqarish uchun sizda <xliff:g id="NUMBER_0">%d</xliff:g> ta urinish bor.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM karta faolsizlantirildi. Davom etish uchun PUK kodni kiriting. Yana <xliff:g id="_NUMBER_1">%d</xliff:g> marta urinib ko‘rganingizdan keyin SIM kartadan umuman foydalanib bo‘lmaydi. Batafsil axborot olish uchun tarmoq operatoriga murojaat qiling.</item> + <item quantity="one">SIM karta faolsizlantirildi. Davom etish uchun PUK kodni kiriting. Yana <xliff:g id="_NUMBER_0">%d</xliff:g> marta urinib ko‘rganingizdan keyin SIM kartadan umuman foydalanib bo‘lmaydi. Batafsil axborot olish uchun tarmoq operatoriga murojaat qiling.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml index 67af2bfdfe25..d20b87ecbf59 100644 --- a/packages/SystemUI/res-keyguard/values-vi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">Thiết bị đã không được mở khóa trong <xliff:g id="NUMBER_0">%d</xliff:g> giờ. Xác nhận mật khẩu.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Không nhận dạng được"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">Hãy nhập mã PIN của SIM, bạn còn <xliff:g id="NUMBER_1">%d</xliff:g> lần thử.</item> + <item quantity="one">Hãy nhập mã PIN của SIM, bạn còn <xliff:g id="NUMBER_0">%d</xliff:g> lần thử trước khi bạn phải liên hệ với nhà cung cấp dịch vụ để mở khóa thiết bị của mình.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM hiện đã bị tắt. Hãy nhập mã PUK để tiếp tục. Bạn còn <xliff:g id="_NUMBER_1">%d</xliff:g> lần thử trước khi SIM vĩnh viễn không sử dụng được. Hãy liên hệ với nhà cung cấp dịch vụ để biết chi tiết.</item> + <item quantity="one">SIM hiện đã bị tắt. Hãy nhập mã PUK để tiếp tục. Bạn còn <xliff:g id="_NUMBER_0">%d</xliff:g> lần thử trước khi SIM vĩnh viễn không thể sử dụng được. Hãy liên hệ với nhà cung cấp dịch vụ để biết chi tiết.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml index d523c20cc5ac..8ee5812f36aa 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">设备已保持锁定状态达 <xliff:g id="NUMBER_0">%d</xliff:g> 小时。请确认密码。</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"无法识别"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">请输入 SIM 卡 PIN 码,您还可以尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> + <item quantity="one">请输入 SIM 卡 PIN 码,您还可以尝试 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍不正确,则需要联系运营商帮您解锁设备。</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM 卡现已停用,请输入 PUK 码继续使用。您还可以尝试 <xliff:g id="_NUMBER_1">%d</xliff:g> 次。如果仍不正确,该 SIM 卡将永远无法使用。有关详情,请联系您的运营商。</item> + <item quantity="one">SIM 卡现已停用,请输入 PUK 码继续使用。您还可以尝试 <xliff:g id="_NUMBER_0">%d</xliff:g> 次。如果仍不正确,该 SIM 卡将永远无法使用。有关详情,请联系您的运营商。</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml index f34314178ebf..5b0754e6e344 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">裝置在過去 <xliff:g id="NUMBER_0">%d</xliff:g> 小時內未有解鎖,請確認密碼。</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"未能識別"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">輸入 SIM 卡的 PIN,您還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> + <item quantity="one">輸入 SIM 卡的 PIN,您還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然輸入錯誤,您必須聯絡流動網絡供應商解鎖您的裝置。</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM 卡已停用。請輸入 PUK 碼以繼續進行。您還可以再試 <xliff:g id="_NUMBER_1">%d</xliff:g> 次。如果仍然輸入錯誤,SIM 卡將永久無法使用。詳情請與流動網絡供應商聯絡。</item> + <item quantity="one">SIM 卡已停用。請輸入 PUK 碼以繼續進行。您還可以再試 <xliff:g id="_NUMBER_0">%d</xliff:g> 次。如果仍然輸入錯誤,SIM 卡將永久無法使用。詳情請與流動網絡供應商聯絡。</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml index 9e0165a90466..45ab5938a286 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml @@ -135,4 +135,12 @@ <item quantity="one">裝置已有 <xliff:g id="NUMBER_0">%d</xliff:g> 小時未解鎖。請確認密碼。</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"無法識別"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="other">請輸入 SIM 卡的 PIN 碼,你還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> + <item quantity="one">請輸入 SIM 卡的 PIN 碼,你還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然失敗,就必須請電信業者為裝置解鎖。</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="other">SIM 卡現在已遭停用。請輸入 PUK 碼以繼續進行。你還可以再試 <xliff:g id="_NUMBER_1">%d</xliff:g> 次,如果仍然失敗,SIM 卡將永久無法使用。詳情請與電信業者聯絡。</item> + <item quantity="one">SIM 卡現在已遭停用。請輸入 PUK 碼以繼續進行。你還可以再試 <xliff:g id="_NUMBER_0">%d</xliff:g> 次,如果仍然失敗,SIM 卡將永久無法使用。詳情請與電信業者聯絡。</item> + </plurals> </resources> diff --git a/packages/SystemUI/res-keyguard/values-zu/strings.xml b/packages/SystemUI/res-keyguard/values-zu/strings.xml index 2f456bd474f3..2329320bdf30 100644 --- a/packages/SystemUI/res-keyguard/values-zu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zu/strings.xml @@ -135,4 +135,12 @@ <item quantity="other">Idivayisi ayikavulwa ngamahora angu-<xliff:g id="NUMBER_1">%d</xliff:g>. Qinisekisa iphasiwedi.</item> </plurals> <string name="fingerprint_not_recognized" msgid="348813995267914625">"Akubonwa"</string> + <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943"> + <item quantity="one">Faka i-PIN ye-SIM, unemizamo engu-<xliff:g id="NUMBER_1">%d</xliff:g> esele.</item> + <item quantity="other">Faka i-PIN ye-SIM, unemizamo engu-<xliff:g id="NUMBER_1">%d</xliff:g> esele.</item> + </plurals> + <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> + <item quantity="one">I-SIM manje ikhutshaziwe. Faka ikhodi ye-PUK ukuze uqhubeke. Unemizamo engu-<xliff:g id="_NUMBER_1">%d</xliff:g> esele ngaphambi kokuthi i-SIM ingasebenziseki unaphakade. Xhumana nenkampani yenethiwekhi ngemininingwane.</item> + <item quantity="other">I-SIM manje ikhutshaziwe. Faka ikhodi ye-PUK ukuze uqhubeke. Unemizamo engu-<xliff:g id="_NUMBER_1">%d</xliff:g> esele ngaphambi kokuthi i-SIM ingasebenziseki unaphakade. Xhumana nenkampani yenethiwekhi ngemininingwane.</item> + </plurals> </resources> diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml index f5637944e72e..bab1e5e4698f 100644 --- a/packages/SystemUI/res/layout/volume_dialog.xml +++ b/packages/SystemUI/res/layout/volume_dialog.xml @@ -32,6 +32,7 @@ android:id="@+id/volume_dialog_content" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_toStartOf="@id/expand" android:clipChildren="false" android:clipToPadding="false" android:orientation="vertical" > @@ -44,54 +45,83 @@ <!-- volume rows added and removed here! :-) --> </LinearLayout> - <!-- special row for ringer mode --> - <RelativeLayout - android:id="@+id/ringer_mode" - android:layout_width="match_parent" + + </LinearLayout> + <LinearLayout + android:id="@+id/expand" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_alignParentEnd="true" + android:layout_alignParentTop="true" + android:layout_marginEnd="@dimen/volume_expander_margin_end" > + <TextView + android:layout_width="wrap_content" android:layout_height="wrap_content" - android:background="@drawable/rounded_bg_full" - android:clipChildren="false" - android:clipToPadding="false" - android:layout_margin="10dp"> + android:ellipsize="end" + android:maxLines="1" + android:textAppearance="@style/TextAppearance.Volume.Header" /> + <com.android.keyguard.AlphaOptimizedImageButton + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/volume_expand_button" + style="@style/VolumeButtons" + android:layout_width="@dimen/volume_button_size" + android:layout_height="@dimen/volume_button_size" + android:clickable="true" + android:soundEffectsEnabled="false" + android:src="@drawable/ic_volume_collapse_animation" + android:background="@drawable/ripple_drawable" + tools:ignore="RtlHardcoded" /> + </LinearLayout> + <!-- special row for ringer mode --> + <RelativeLayout + android:id="@+id/ringer_mode" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@drawable/rounded_bg_full" + android:clipChildren="false" + android:clipToPadding="false" + android:layout_below="@id/volume_dialog_content" + android:layout_margin="10dp"> - <com.android.keyguard.AlphaOptimizedImageButton - android:id="@+id/ringer_icon" - style="@style/VolumeButtons" - android:background="?android:selectableItemBackgroundBorderless" - android:layout_width="@dimen/volume_button_size" - android:layout_height="@dimen/volume_button_size" - android:layout_alignParentStart="true" - android:layout_centerVertical="true" - android:soundEffectsEnabled="false" /> + <com.android.keyguard.AlphaOptimizedImageButton + android:id="@+id/ringer_icon" + style="@style/VolumeButtons" + android:background="?android:selectableItemBackgroundBorderless" + android:layout_width="@dimen/volume_button_size" + android:layout_height="@dimen/volume_button_size" + android:layout_alignParentStart="true" + android:layout_centerVertical="true" + android:soundEffectsEnabled="false" /> - <TextView - android:id="@+id/ringer_title" - android:text="@string/stream_ring" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:ellipsize="end" - android:maxLines="1" - android:layout_alignParentStart="true" - android:layout_centerVertical="true" - android:layout_toEndOf="@+id/ringer_icon" - android:layout_marginStart="64dp" - android:textColor="?android:attr/colorControlNormal" - android:textAppearance="?android:attr/textAppearanceSmall" - android:paddingStart="@dimen/volume_row_header_padding_start" /> + <TextView + android:id="@+id/ringer_title" + android:text="@string/stream_ring" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ellipsize="end" + android:maxLines="1" + android:layout_alignParentStart="true" + android:layout_centerVertical="true" + android:layout_toEndOf="@+id/ringer_icon" + android:layout_marginStart="64dp" + android:textColor="?android:attr/colorControlNormal" + android:textAppearance="?android:attr/textAppearanceSmall" + android:paddingStart="@dimen/volume_row_header_padding_start" /> - <TextView - android:id="@+id/ringer_status" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:ellipsize="end" - android:layout_alignParentEnd="true" - android:layout_centerVertical="true" - android:layout_marginEnd="14dp" - android:maxLines="1" - android:textColor="?android:attr/colorControlNormal" - android:textAppearance="?android:attr/textAppearanceSmall" /> + <TextView + android:id="@+id/ringer_status" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ellipsize="end" + android:layout_alignParentEnd="true" + android:layout_centerVertical="true" + android:layout_marginEnd="14dp" + android:maxLines="1" + android:textColor="?android:attr/colorControlNormal" + android:textAppearance="?android:attr/textAppearanceSmall" /> - </RelativeLayout> - </LinearLayout> + </RelativeLayout> </RelativeLayout> </com.android.systemui.volume.VolumeUiLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index e5270893a453..b9a228f7d538 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Dubbele multitoonfrekwensie"</string> <string name="stream_accessibility" msgid="301136219144385106">"Toeganklikheid"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Lui"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibreer"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Demp"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tik om te ontdemp."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tik om op vibreer te stel. Toeganklikheidsdienste kan dalk gedemp wees."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tik om te demp. Toeganklikheidsdienste kan dalk gedemp wees."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Kitsprogramme"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Kitsprogramme hoef nie geïnstalleer te word nie."</string> <string name="app_info" msgid="6856026610594615344">"Programinligting"</string> - <string name="go_to_web" msgid="1106022723459948514">"Gaan na web"</string> + <string name="go_to_web" msgid="2650669128861626071">"Gaan na blaaier"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobiele data"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is af"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is af"</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 8ee77e149308..961ac4514477 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"ብሉቱዝ"</string> <string name="stream_dtmf" msgid="2447177903892477915">"ድርብ ባለ በርካታ ቅላጼ ድግምግሞሽ"</string> <string name="stream_accessibility" msgid="301136219144385106">"ተደራሽነት"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"ጥሪ"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"ንዘር"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"ድምጸ-ከል አድርግ"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s። ድምጸ-ከል ለማድረግ መታ ያድርጉ"</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s። ወደ ንዝረት ለማቀናበር መታ ያድርጉ። የተደራሽነት አገልግሎቶች ድምጸ-ከል ሊደረግባቸው ይችላል።"</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s። ድምጸ-ከል ለማድረግ መታ ያድርጉ። የተደራሽነት አገልግሎቶች ድምጸ-ከል ሊደረግባቸው ይችላል።"</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"የቅጽበት መተግበሪያዎች"</string> <string name="instant_apps_message" msgid="8116608994995104836">"ቅጽበታዊ መተግበሪያዎች መጫን አያስፈልጋቸውም።"</string> <string name="app_info" msgid="6856026610594615344">"የመተግበሪያ መረጃ"</string> - <string name="go_to_web" msgid="1106022723459948514">"ወደ ድር ሂድ"</string> + <string name="go_to_web" msgid="2650669128861626071">"ወደ አሳሽ ሂድ"</string> <string name="mobile_data" msgid="7094582042819250762">"የተንቀሳቃሽ ስልክ ውሂብ"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ጠፍቷል"</string> <string name="bt_is_off" msgid="2640685272289706392">"ብሉቱዝ ጠፍቷል"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 48e8739f443b..8437705e3cd2 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -500,6 +500,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"بلوتوث"</string> <string name="stream_dtmf" msgid="2447177903892477915">"تردد ثنائي متعدد النغمات"</string> <string name="stream_accessibility" msgid="301136219144385106">"إمكانية الوصول"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"استصدار رنين"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"اهتزاز"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"كتم الصوت"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. انقر لإلغاء التجاهل."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. انقر للتعيين على الاهتزاز. قد يتم تجاهل خدمات إمكانية الوصول."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. انقر للتجاهل. قد يتم تجاهل خدمات إمكانية الوصول."</string> @@ -780,7 +783,7 @@ <string name="instant_apps" msgid="6647570248119804907">"التطبيقات الفورية"</string> <string name="instant_apps_message" msgid="8116608994995104836">"لا تتطلب التطبيقات الفورية إجراء التثبيت."</string> <string name="app_info" msgid="6856026610594615344">"معلومات عن التطبيق"</string> - <string name="go_to_web" msgid="1106022723459948514">"الانتقال إلى الويب"</string> + <string name="go_to_web" msgid="2650669128861626071">"الانتقال إلى المتصفح"</string> <string name="mobile_data" msgid="7094582042819250762">"بيانات الجوّال"</string> <string name="wifi_is_off" msgid="1838559392210456893">"تم إيقاف شبكة Wi-Fi"</string> <string name="bt_is_off" msgid="2640685272289706392">"تم إيقاف البلوتوث."</string> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index de9ffe1bb8c1..098b1cdc5d35 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Çoxsaylı ton olan ikili tezlik"</string> <string name="stream_accessibility" msgid="301136219144385106">"Münasiblik"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Zəng"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrasiya"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Susdurun"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Səsli etmək üçün tıklayın."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Vibrasiyanı ayarlamaq üçün tıklayın. Əlçatımlılıq xidmətləri səssiz edilmiş ola bilər."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Səssiz etmək üçün tıklayın. Əlçatımlılıq xidmətləri səssiz edilmiş ola bilər."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Ani Tətbiqlər"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Ani tətbiqlər quraşdırma tələb etmir."</string> <string name="app_info" msgid="6856026610594615344">"Tətbiq məlumatı"</string> - <string name="go_to_web" msgid="1106022723459948514">"Vebə keçin"</string> + <string name="go_to_web" msgid="2650669128861626071">"Brauzerə daxil edin"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobil data"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi deaktivdir"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth deaktivdir"</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index 4e38e5dbe92e..ae3854fb95af 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Višestruka frekvencija dualnog tona"</string> <string name="stream_accessibility" msgid="301136219144385106">"Pristupačnost"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Aktiviraj zvono"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibriraj"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Isključi zvuk"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Dodirnite da biste uključili zvuk."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Dodirnite da biste podesili na vibraciju. Zvuk usluga pristupačnosti će možda biti isključen."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Dodirnite da biste isključili zvuk. Zvuk usluga pristupačnosti će možda biti isključen."</string> @@ -762,7 +765,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Instant aplikacije"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Instant aplikacije ne zahtevaju instalaciju."</string> <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string> - <string name="go_to_web" msgid="1106022723459948514">"Idi na veb"</string> + <string name="go_to_web" msgid="2650669128861626071">"Idi na pregledač"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobilni podaci"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je isključen"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je isključen"</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index c077c0395523..3c9f83afc828 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -498,6 +498,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Двухтанальны шматчастотны"</string> <string name="stream_accessibility" msgid="301136219144385106">"Спецыяльныя магчымасці"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Званок"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Вібрацыя"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Гук выключаны"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Дакраніцеся, каб уключыць гук."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Дакраніцеся, каб уключыць вібрацыю. Можа быць адключаны гук службаў спецыяльных магчымасцей."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Дакраніцеся, каб адключыць гук. Можа быць адключаны гук службаў спецыяльных магчымасцей."</string> @@ -770,7 +773,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Імгненныя праграмы"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Імгненныя праграмы не патрабуюць усталёўкі."</string> <string name="app_info" msgid="6856026610594615344">"Інфармацыя пра праграму"</string> - <string name="go_to_web" msgid="1106022723459948514">"Перайсці ў інтэрнэт"</string> + <string name="go_to_web" msgid="2650669128861626071">"Перайсці ў браўзер"</string> <string name="mobile_data" msgid="7094582042819250762">"Маб. перадача даных"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi выключаны"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth выключаны"</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index c567adfff383..1cd4c910c54d 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Тонално набиране"</string> <string name="stream_accessibility" msgid="301136219144385106">"Достъпност"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Позвъняване"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Вибриране"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Без звук"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Докоснете, за да включите отново звука."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Докоснете, за да зададете вибриране. Възможно е звукът на услугите за достъпност да бъде заглушен."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Докоснете, за да заглушите звука. Възможно е звукът на услугите за достъпност да бъде заглушен."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Мигновени приложения"</string> <string name="instant_apps_message" msgid="8116608994995104836">"За мигновените приложения не се изисква инсталиране."</string> <string name="app_info" msgid="6856026610594615344">"Информация за приложението"</string> - <string name="go_to_web" msgid="1106022723459948514">"Към мрежата"</string> + <string name="go_to_web" msgid="2650669128861626071">"Към браузъра"</string> <string name="mobile_data" msgid="7094582042819250762">"Мобилни данни"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Функцията за Wi‑Fi е изключена"</string> <string name="bt_is_off" msgid="2640685272289706392">"Функцията за Bluetooth е изключена"</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 577077929352..c82352553f95 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -492,6 +492,12 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"ব্লুটুথ"</string> <string name="stream_dtmf" msgid="2447177903892477915">"ডুয়েল মাল্টি টোন ফ্রিকোয়েন্সি"</string> <string name="stream_accessibility" msgid="301136219144385106">"অ্যাক্সেসযোগ্যতা"</string> + <!-- no translation found for volume_ringer_status_normal (4273142424125855384) --> + <skip /> + <!-- no translation found for volume_ringer_status_vibrate (1825615171021346557) --> + <skip /> + <!-- no translation found for volume_ringer_status_silent (6896394161022916369) --> + <skip /> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s। সশব্দ করতে আলতো চাপুন।"</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s। কম্পন এ সেট করতে আলতো চাপুন। অ্যাক্সেসযোগ্যতার পরিষেবাগুলিকে নিঃশব্দ করা হতে পারে।"</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s। নিঃশব্দ করতে আলতো চাপুন। অ্যাক্সেসযোগ্যতার পরিষেবাগুলিকে নিঃশব্দ করা হতে পারে।"</string> @@ -756,8 +762,7 @@ <string name="instant_apps" msgid="6647570248119804907">"ঝটপট অ্যাপ"</string> <string name="instant_apps_message" msgid="8116608994995104836">"ঝটপট অ্যাপ ইনস্টল করার প্রয়োজন হয় না।"</string> <string name="app_info" msgid="6856026610594615344">"অ্যাপের তথ্য"</string> - <!-- no translation found for go_to_web (2650669128861626071) --> - <skip /> + <string name="go_to_web" msgid="2650669128861626071">"ব্রাউজারে যান"</string> <string name="mobile_data" msgid="7094582042819250762">"মোবাইল ডেটা"</string> <string name="wifi_is_off" msgid="1838559392210456893">"ওয়াই ফাই বন্ধ আছে"</string> <string name="bt_is_off" msgid="2640685272289706392">"ব্লুটুথ বন্ধ আছে"</string> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 530c1a8b56aa..f09bb1f29c4b 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Dvostruka višemelodijska frekvencija"</string> <string name="stream_accessibility" msgid="301136219144385106">"Pristupačnost"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Zvono"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibriranje"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Isključi zvuk"</string> <!-- String.format failed for translation --> <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) --> <skip /> @@ -764,8 +767,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Instant-aplikacije"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Za instant aplikacije nije potrebna instalacija"</string> <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string> - <!-- no translation found for go_to_web (2650669128861626071) --> - <skip /> + <string name="go_to_web" msgid="2650669128861626071">"Idi na preglednik"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobilni podaci"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi veza je isključena"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je isključen"</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 1c5fe909ca9a..e87bb45247f5 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Marcatge per tons"</string> <string name="stream_accessibility" msgid="301136219144385106">"Accessibilitat"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Fes sonar"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibra"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Silencia"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Toca per activar el so."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Toca per activar la vibració. Pot ser que els serveis d\'accessibilitat se silenciïn."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Toca per silenciar el so. Pot ser que els serveis d\'accessibilitat se silenciïn."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Aplicacions instantànies"</string> <string name="instant_apps_message" msgid="8116608994995104836">"No cal instal·lar les aplicacions instantànies."</string> <string name="app_info" msgid="6856026610594615344">"Informació de l\'aplicació"</string> - <string name="go_to_web" msgid="1106022723459948514">"Ves al web"</string> + <string name="go_to_web" msgid="2650669128861626071">"Ves al navegador"</string> <string name="mobile_data" msgid="7094582042819250762">"Dades mòbils"</string> <string name="wifi_is_off" msgid="1838559392210456893">"La Wi-Fi està desactivada"</string> <string name="bt_is_off" msgid="2640685272289706392">"El Bluetooth està desactivat"</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index b1cddfb2a5cc..e0e14a16ce3b 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -498,6 +498,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Tónová volba"</string> <string name="stream_accessibility" msgid="301136219144385106">"Přístupnost"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Vyzvánění"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrace"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Ztlumení"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Klepnutím zapnete zvuk."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Klepnutím aktivujete režim vibrací. Služby přístupnosti mohou být ztlumeny."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Klepnutím vypnete zvuk. Služby přístupnosti mohou být ztlumeny."</string> @@ -770,7 +773,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Okamžité aplikace"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Okamžité aplikace není třeba instalovat."</string> <string name="app_info" msgid="6856026610594615344">"O aplikaci"</string> - <string name="go_to_web" msgid="1106022723459948514">"Přejít na web"</string> + <string name="go_to_web" msgid="2650669128861626071">"Přejít do prohlížeče"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobilní data"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je vypnuta"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je vypnuto"</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index e4198f3c157b..fb886fc6dd64 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Tonesignalfrekvens (DTMF)"</string> <string name="stream_accessibility" msgid="301136219144385106">"Hjælpefunktioner"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Ring"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibration"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Slå lyden fra"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tryk for at slå lyden til."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tryk for at konfigurere til at vibrere. Tilgængelighedstjenester kan blive deaktiveret."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tryk for at slå lyden fra. Lyden i tilgængelighedstjenester kan blive slået fra."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Instant apps kræver ingen installation."</string> <string name="app_info" msgid="6856026610594615344">"Appinfo"</string> - <string name="go_to_web" msgid="1106022723459948514">"Gå til website"</string> + <string name="go_to_web" msgid="2650669128861626071">"Gå til en browser"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobildata"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi er slået fra"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth er slået fra"</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index e9c2f26dfb82..feb7064be29f 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -496,6 +496,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Doppelton-Mehrfrequenz"</string> <string name="stream_accessibility" msgid="301136219144385106">"Bedienungshilfen"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Klingeln lassen"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrieren"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Stummschalten"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Zum Aufheben der Stummschaltung tippen."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tippen, um Vibrieren festzulegen. Bedienungshilfen werden unter Umständen stummgeschaltet."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Zum Stummschalten tippen. Bedienungshilfen werden unter Umständen stummgeschaltet."</string> @@ -760,7 +763,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Instant-Apps"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Bei Instant-Apps ist keine vorherige Installation erforderlich."</string> <string name="app_info" msgid="6856026610594615344">"App-Informationen"</string> - <string name="go_to_web" msgid="1106022723459948514">"Web aufrufen"</string> + <string name="go_to_web" msgid="2650669128861626071">"Browser öffnen"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobile Daten"</string> <string name="wifi_is_off" msgid="1838559392210456893">"WLAN ist deaktiviert"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ist deaktiviert"</string> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 33df73b82030..1fe90101e41f 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Πολυσυχνότητα διπλού τόνου"</string> <string name="stream_accessibility" msgid="301136219144385106">"Προσβασιμότητα"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Κουδούνισμα"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Δόνηση"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Σίγαση"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Πατήστε για κατάργηση σίγασης."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Πατήστε για ενεργοποιήσετε τη δόνηση. Οι υπηρεσίες προσβασιμότητας ενδέχεται να τεθούν σε σίγαση."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Πατήστε για σίγαση. Οι υπηρεσίες προσβασιμότητας ενδέχεται να τεθούν σε σίγαση."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Instant Εφαρμογές"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Οι Instant Εφαρμογές δεν απαιτούν εγκατάσταση."</string> <string name="app_info" msgid="6856026610594615344">"Πληροφορίες εφαρμογής"</string> - <string name="go_to_web" msgid="1106022723459948514">"Μετάβαση στον ιστό"</string> + <string name="go_to_web" msgid="2650669128861626071">"Μετάβ. σε πρόγ. περ."</string> <string name="mobile_data" msgid="7094582042819250762">"Δεδομένα κινητής τηλεφωνίας"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Το Wi-Fi είναι ανενεργό"</string> <string name="bt_is_off" msgid="2640685272289706392">"Το Bluetooth είναι ανενεργό"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index c97f7d32ee26..4af3f5912d36 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Multifrecuencia de tono doble"</string> <string name="stream_accessibility" msgid="301136219144385106">"Accesibilidad"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Hacer sonar"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrar"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Silenciar"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Presiona para dejar de silenciar."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Presiona para establecer el modo vibración. Es posible que los servicios de accesibilidad estén silenciados."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Presiona para silenciar. Es posible que los servicios de accesibilidad estén silenciados."</string> @@ -758,7 +761,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Apps instantáneas"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Las Apps instantáneas no requieren instalación."</string> <string name="app_info" msgid="6856026610594615344">"Información de apps"</string> - <string name="go_to_web" msgid="1106022723459948514">"Ir a la Web"</string> + <string name="go_to_web" msgid="2650669128861626071">"Ir al navegador"</string> <string name="mobile_data" msgid="7094582042819250762">"Datos móviles"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi desactivado"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desactivado"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 94467d849204..14c28183c6de 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Multifrecuencia de tono dual"</string> <string name="stream_accessibility" msgid="301136219144385106">"Accesibilidad"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Hacer sonar"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrar"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Silenciar"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Toca para activar el sonido."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Toca para poner el dispositivo en vibración. Los servicios de accesibilidad pueden silenciarse."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Toca para silenciar. Los servicios de accesibilidad pueden silenciarse."</string> @@ -758,7 +761,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Aplicaciones Instantáneas"</string> <string name="instant_apps_message" msgid="8116608994995104836">"No es necesario instalar las Aplicaciones Instantáneas."</string> <string name="app_info" msgid="6856026610594615344">"Información de la aplicación"</string> - <string name="go_to_web" msgid="1106022723459948514">"Ir a la Web"</string> + <string name="go_to_web" msgid="2650669128861626071">"Ir al navegador"</string> <string name="mobile_data" msgid="7094582042819250762">"Datos móviles"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi desactivado"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desactivado"</string> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 3a4eea6a1d67..27e4920b341e 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Kaks mitme tooniga sagedust"</string> <string name="stream_accessibility" msgid="301136219144385106">"Juurdepääsetavus"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Helisemine"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibreerimine"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Vaigistatud"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Puudutage vaigistuse tühistamiseks."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Puudutage värinarežiimi määramiseks. Juurdepääsetavuse teenused võidakse vaigistada."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Puudutage vaigistamiseks. Juurdepääsetavuse teenused võidakse vaigistada."</string> @@ -758,7 +761,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Installimata avatavad rakendused"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Installimata avatavaid rakendusi pole vaja installida."</string> <string name="app_info" msgid="6856026610594615344">"Rakenduse teave"</string> - <string name="go_to_web" msgid="1106022723459948514">"Avage veebis"</string> + <string name="go_to_web" msgid="2650669128861626071">"Ava brauser"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobiilne andmeside"</string> <string name="wifi_is_off" msgid="1838559392210456893">"WiFi on välja lülitatud"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth on välja lülitatud"</string> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index b75548e55f81..5d4181e124fe 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth konexioa"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Tonu anitzeko maiztasun duala"</string> <string name="stream_accessibility" msgid="301136219144385106">"Erabilerraztasuna"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Jo tonua"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Dardara"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Ez jo tonua"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Sakatu audioa aktibatzeko."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Sakatu dardara ezartzeko. Baliteke erabilerraztasun-eginbideen audioa desaktibatzea."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Sakatu audioa desaktibatzeko. Baliteke erabilerraztasun-eginbideen audioa desaktibatzea."</string> @@ -758,7 +761,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Zuzeneko aplikazioak"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Zuzeneko aplikazioak ez dira instalatu behar."</string> <string name="app_info" msgid="6856026610594615344">"Aplikazioari buruzko informazioa"</string> - <string name="go_to_web" msgid="1106022723459948514">"Joan sarera"</string> + <string name="go_to_web" msgid="2650669128861626071">"Joan arakatzailera"</string> <string name="mobile_data" msgid="7094582042819250762">"Datu mugikorrak"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi konexioa desaktibatuta dago"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth konexioa desaktibatuta dago"</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index d107fea93d3c..9360c1dfa614 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"بلوتوث"</string> <string name="stream_dtmf" msgid="2447177903892477915">"فرکانس دوتایی چند نوایی"</string> <string name="stream_accessibility" msgid="301136219144385106">"دسترسپذیری"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"زنگ زدن"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"لرزش"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"بیصدا"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. برای باصدا کردن ضربه بزنید."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. برای تنظیم روی لرزش ضربه بزنید. ممکن است سرویسهای دسترسپذیری بیصدا شوند."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. برای بیصدا کردن ضربه بزنید. ممکن است سرویسهای دسترسپذیری بیصدا شوند."</string> @@ -756,8 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"برنامههای فوری"</string> <string name="instant_apps_message" msgid="8116608994995104836">"برنامههای فوری نیاز به نصب ندارند."</string> <string name="app_info" msgid="6856026610594615344">"اطلاعات برنامه"</string> - <!-- no translation found for go_to_web (2650669128861626071) --> - <skip /> + <string name="go_to_web" msgid="2650669128861626071">"رفتن به مرورگر"</string> <string name="mobile_data" msgid="7094582042819250762">"داده تلفن همراه"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi خاموش است"</string> <string name="bt_is_off" msgid="2640685272289706392">"بلوتوث خاموش است"</string> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index ccec4a62eb9b..864f8d0bb2f0 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Äänitaajuusvalinta"</string> <string name="stream_accessibility" msgid="301136219144385106">"Esteettömyys"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Soittoääni"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Värinä"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Äänetön"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Poista mykistys koskettamalla."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Siirry värinätilaan koskettamalla. Myös esteettömyyspalvelut saattavat mykistyä."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Mykistä koskettamalla. Myös esteettömyyspalvelut saattavat mykistyä."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Pikasovelluksia ei tarvitse asentaa."</string> <string name="app_info" msgid="6856026610594615344">"Sovelluksen tiedot"</string> - <string name="go_to_web" msgid="1106022723459948514">"Avaa verkossa"</string> + <string name="go_to_web" msgid="2650669128861626071">"Siirry selaimeen"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobiilitiedonsiirto"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi on pois käytöstä"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ei ole käytössä"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index bdd01c211a06..5c4394b86726 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Fréquence double multi ton"</string> <string name="stream_accessibility" msgid="301136219144385106">"Accessibilité"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Sonnerie"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibration"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Sonnerie désactivée"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Touchez pour réactiver le son."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Touchez pour activer les vibrations. Il est possible de couper le son des services d\'accessibilité."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Touchez pour couper le son. Il est possible de couper le son des services d\'accessibilité."</string> @@ -758,7 +761,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Applications instantanées"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Les applications instantanées ne nécessitent pas d\'installation."</string> <string name="app_info" msgid="6856026610594615344">"Détails de l\'application"</string> - <string name="go_to_web" msgid="1106022723459948514">"Accéder au Web"</string> + <string name="go_to_web" msgid="2650669128861626071">"Ouvrir le navigateur"</string> <string name="mobile_data" msgid="7094582042819250762">"Données cellulaires"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Le Wi-Fi est désactivé"</string> <string name="bt_is_off" msgid="2640685272289706392">"Le Bluetooth est désactivé"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index ee50e566e44e..21952aea6ea8 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"DTMF"</string> <string name="stream_accessibility" msgid="301136219144385106">"Accessibilité"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Sonnerie"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibreur"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Silencieux"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Appuyez pour ne plus ignorer."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Appuyez pour mettre en mode vibreur. Vous pouvez ignorer les services d\'accessibilité."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Appuyez pour ignorer. Vous pouvez ignorer les services d\'accessibilité."</string> @@ -758,7 +761,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Applis instantanées"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Les applis instantanées ne nécessitent pas d\'installation."</string> <string name="app_info" msgid="6856026610594615344">"Infos sur l\'appli"</string> - <string name="go_to_web" msgid="1106022723459948514">"Accéder au site Web"</string> + <string name="go_to_web" msgid="2650669128861626071">"Accéder au navigateur"</string> <string name="mobile_data" msgid="7094582042819250762">"Données mobiles"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi désactivé"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth désactivé"</string> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 558b98c29347..a3d580be0ad6 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Multifrecuencia de dobre ton"</string> <string name="stream_accessibility" msgid="301136219144385106">"Accesibilidade"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Facer soar"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrar"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Silenciar"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Toca para activar o son."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Toca para establecer a vibración. Pódense silenciar os servizos de accesibilidade."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Toca para silenciar. Pódense silenciar os servizos de accesibilidade."</string> @@ -758,7 +761,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Aplicacións instantáneas"</string> <string name="instant_apps_message" msgid="8116608994995104836">"As aplicacións instantáneas non precisan instalación."</string> <string name="app_info" msgid="6856026610594615344">"Info. da aplicación"</string> - <string name="go_to_web" msgid="1106022723459948514">"Acceder á web"</string> + <string name="go_to_web" msgid="2650669128861626071">"Ir ao navegador"</string> <string name="mobile_data" msgid="7094582042819250762">"Datos móbiles"</string> <string name="wifi_is_off" msgid="1838559392210456893">"A wifi está desactivada"</string> <string name="bt_is_off" msgid="2640685272289706392">"O Bluetooth está desactivado"</string> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 139ab827f4ef..83f789693518 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -34,17 +34,14 @@ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"નોટિફિકેશનો"</string> <string name="battery_low_title" msgid="6456385927409742437">"બૅટરી ઓછી છે"</string> <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> બાકી"</string> - <!-- no translation found for battery_low_percent_format_saver_started (7879389868952879166) --> - <skip /> + <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> બાકી. બૅટરી સેવર ચાલુ છે."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB ચાર્જિંગ સમર્થિત નથી.\nફક્ત આપવામાં આવેલ ચાર્જરનો ઉપયોગ કરો."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB ચાર્જિંગ સમર્થિત નથી."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"ફક્ત પ્રદાન કરાયેલ ચાર્જરનો ઉપયોગ કરો."</string> <string name="battery_low_why" msgid="4553600287639198111">"સેટિંગ્સ"</string> - <!-- no translation found for battery_saver_confirmation_title (2052100465684817154) --> - <skip /> + <string name="battery_saver_confirmation_title" msgid="2052100465684817154">"બૅટરી સેવર ચાલુ કરીએ?"</string> <string name="battery_saver_confirmation_ok" msgid="7507968430447930257">"ચાલુ કરો"</string> - <!-- no translation found for battery_saver_start_action (8187820911065797519) --> - <skip /> + <string name="battery_saver_start_action" msgid="8187820911065797519">"બૅટરી સેવર ચાલુ કરો"</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"સેટિંગ્સ"</string> <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"વાઇ-ફાઇ"</string> <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"સ્ક્રીનને આપમેળે ફેરવો"</string> @@ -402,11 +399,9 @@ <string name="user_remove_user_title" msgid="4681256956076895559">"વપરાશકર્તાને દૂર કરીએ?"</string> <string name="user_remove_user_message" msgid="1453218013959498039">"આ વપરાશકર્તાની તમામ ઍપ્લિકેશનો અને ડેટા કાઢી નાખવામાં આવશે."</string> <string name="user_remove_user_remove" msgid="7479275741742178297">"દૂર કરો"</string> - <!-- no translation found for battery_saver_notification_title (8614079794522291840) --> - <skip /> + <string name="battery_saver_notification_title" msgid="8614079794522291840">"બૅટરી સેવર ચાલુ છે"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"પ્રદર્શન અને બૅકગ્રાઉન્ડ ડેટા ઘટાડે છે"</string> - <!-- no translation found for battery_saver_notification_action_text (132118784269455533) --> - <skip /> + <string name="battery_saver_notification_action_text" msgid="132118784269455533">"બૅટરી સેવર બંધ કરો"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> તમારી સ્ક્રીન પર જે પ્રદર્શિત થાય છે તે દરેક વસ્તુને કેપ્ચર કરવાનું પ્રારંભ કરશે."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"ફરીથી બતાવશો નહીં"</string> <string name="clear_all_notifications_text" msgid="814192889771462828">"બધુ સાફ કરો"</string> @@ -497,6 +492,12 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"બ્લૂટૂથ"</string> <string name="stream_dtmf" msgid="2447177903892477915">"દ્વિ બહુ ટોન આવર્તન"</string> <string name="stream_accessibility" msgid="301136219144385106">"ઍક્સેસિબિલિટી"</string> + <!-- no translation found for volume_ringer_status_normal (4273142424125855384) --> + <skip /> + <!-- no translation found for volume_ringer_status_vibrate (1825615171021346557) --> + <skip /> + <!-- no translation found for volume_ringer_status_silent (6896394161022916369) --> + <skip /> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. અનમ્યૂટ કરવા માટે ટૅપ કરો."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. વાઇબ્રેટ પર સેટ કરવા માટે ટૅપ કરો. ઍક્સેસિબિલિટી સેવાઓ મ્યૂટ કરવામાં આવી શકે છે."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. મ્યૂટ કરવા માટે ટૅપ કરો. ઍક્સેસિબિલિટી સેવાઓ મ્યૂટ કરવામાં આવી શકે છે."</string> @@ -761,7 +762,7 @@ <string name="instant_apps" msgid="6647570248119804907">"ઝટપટ ઍપ્લિકેશનો"</string> <string name="instant_apps_message" msgid="8116608994995104836">"ઝટપટ ઍપ્લિકેશનો માટે ઇન્સ્ટૉલેશનની જરૂર નથી."</string> <string name="app_info" msgid="6856026610594615344">"ઍપ્લિકેશન માહિતી"</string> - <string name="go_to_web" msgid="1106022723459948514">"વેબ પર જાઓ"</string> + <string name="go_to_web" msgid="2650669128861626071">"બ્રાઉઝર પર જાઓ"</string> <string name="mobile_data" msgid="7094582042819250762">"મોબાઇલ ડેટા"</string> <string name="wifi_is_off" msgid="1838559392210456893">"વાઇ-ફાઇ બંધ છે"</string> <string name="bt_is_off" msgid="2640685272289706392">"બ્લૂટૂથ બંધ છે"</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 1681c2eeee45..e7fc696dc89e 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"ब्लूटूथ"</string> <string name="stream_dtmf" msgid="2447177903892477915">"दोहरी बहु टोन आवृत्ति"</string> <string name="stream_accessibility" msgid="301136219144385106">"सुलभता"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"आवाज़ चालू है"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"कंपन (वाइब्रेशन)"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"आवाज़ बंद है"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. अनम्यूट करने के लिए टैप करें."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. कंपन पर सेट करने के लिए टैप करें. सुलभता सेवाएं म्यूट हो सकती हैं."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. म्यूट करने के लिए टैप करें. सुलभता सेवाएं म्यूट हो सकती हैं."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"झटपट ऐप्स"</string> <string name="instant_apps_message" msgid="8116608994995104836">"झटपट ऐप्स के लिए इंस्टॉलेशन ज़रूरी नहीं है."</string> <string name="app_info" msgid="6856026610594615344">"ऐप की जानकारी"</string> - <string name="go_to_web" msgid="1106022723459948514">"वेब पर जाएं"</string> + <string name="go_to_web" msgid="2650669128861626071">"ब्राउज़र पर जाएं"</string> <string name="mobile_data" msgid="7094582042819250762">"मोबाइल डेटा"</string> <string name="wifi_is_off" msgid="1838559392210456893">"वाई-फ़ाई बंद है"</string> <string name="bt_is_off" msgid="2640685272289706392">"ब्लूटूथ बंद है"</string> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 699efad0dc03..88f50973cf97 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"DTMF"</string> <string name="stream_accessibility" msgid="301136219144385106">"Pristupačnost"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Zvonjenje"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibriranje"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Zvuk je isključen"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Dodirnite da biste uključili zvuk."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Dodirnite da biste postavili na vibraciju. Usluge pristupačnosti možda neće imati zvuk."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Dodirnite da biste isključili zvuk. Usluge pristupačnosti možda neće imati zvuk."</string> @@ -762,7 +765,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Instant aplikacije"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Instant aplikacije nije potrebno instalirati."</string> <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string> - <string name="go_to_web" msgid="1106022723459948514">"Prijeđi na web"</string> + <string name="go_to_web" msgid="2650669128861626071">"Otvori preglednik"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobilni podaci"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je isključen"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je isključen"</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index faa4a860f5f6..e81df8f54286 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Kéthangú többfrekvenciás jelzésátvitel (DTMF)"</string> <string name="stream_accessibility" msgid="301136219144385106">"Kisegítő lehetőségek"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Csörgés"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Rezgés"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Néma"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Koppintson a némítás megszüntetéséhez."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Koppintson a rezgés beállításához. Előfordulhat, hogy a kisegítő lehetőségek szolgáltatásai le vannak némítva."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Koppintson a némításhoz. Előfordulhat, hogy a kisegítő lehetőségek szolgáltatásai le vannak némítva."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Azonnali alkalmazások"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Az azonnali alkalmazásokat nem kell telepíteni."</string> <string name="app_info" msgid="6856026610594615344">"Alkalmazásinformáció"</string> - <string name="go_to_web" msgid="1106022723459948514">"Tovább az internetre"</string> + <string name="go_to_web" msgid="2650669128861626071">"Ugrás a böngészőbe"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobiladatok"</string> <string name="wifi_is_off" msgid="1838559392210456893">"A Wi-Fi ki van kapcsolva"</string> <string name="bt_is_off" msgid="2640685272289706392">"A Bluetooth ki van kapcsolva"</string> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index 074ca49a292e..2994b9b05e7b 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Կրկնակի բազմերանգ հաճախականություն"</string> <string name="stream_accessibility" msgid="301136219144385106">"Մատչելիություն"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Սովորական"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Թրթռազանգ"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Անձայն"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s: Հպեք՝ ձայնը միացնելու համար:"</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s: Հպեք՝ թրթռումը միացնելու համար: Մատչելիության ծառայությունների ձայնը կարող է անջատվել:"</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s: Հպեք՝ ձայնն անջատելու համար: Մատչելիության ծառայությունների ձայնը կարող է անջատվել:"</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Ակնթարթորեն գործարկվող հավելվածներ"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Ակնթարթորեն գործարկվող հավելվածները տեղադրում չեն պահանջում։"</string> <string name="app_info" msgid="6856026610594615344">"Հավելվածի տվյալներ"</string> - <string name="go_to_web" msgid="1106022723459948514">"Բացեք համացանցում"</string> + <string name="go_to_web" msgid="2650669128861626071">"Անցնել դիտարկիչ"</string> <string name="mobile_data" msgid="7094582042819250762">"Բջջային ինտերնետ"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi-ն անջատված է"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth-ն անջատված է"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index b4709bb4c77d..f8604e3e1b42 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Frekuensi multinada ganda"</string> <string name="stream_accessibility" msgid="301136219144385106">"Aksesibilitas"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Dering"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Getar"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Nonaktifkan"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Ketuk untuk menyuarakan."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Ketuk untuk menyetel agar bergetar. Layanan aksesibilitas mungkin dibisukan."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Ketuk untuk membisukan. Layanan aksesibilitas mungkin dibisukan."</string> @@ -756,8 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Aplikasi Instan"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Aplikasi instan tidak perlu diinstal."</string> <string name="app_info" msgid="6856026610594615344">"Info aplikasi"</string> - <!-- no translation found for go_to_web (2650669128861626071) --> - <skip /> + <string name="go_to_web" msgid="2650669128861626071">"Buka browser"</string> <string name="mobile_data" msgid="7094582042819250762">"Data seluler"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi nonaktif"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth nonaktif"</string> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index f60a766530c1..1efc249e6337 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Tvítóna fjöltíðni"</string> <string name="stream_accessibility" msgid="301136219144385106">"Aðgengi"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Hringing"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Titringur"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Hljóð af"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Ýttu til að hætta að þagga."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Ýttu til að stilla á titring. Hugsanlega verður slökkt á hljóði aðgengisþjónustu."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Ýttu til að þagga. Hugsanlega verður slökkt á hljóði aðgengisþjónustu."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Skyndiforrit"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Skyndiforrit þurfa ekki uppsetningu."</string> <string name="app_info" msgid="6856026610594615344">"Forritsupplýsingar"</string> - <string name="go_to_web" msgid="1106022723459948514">"Fara á vefinn"</string> + <string name="go_to_web" msgid="2650669128861626071">"Opna vafra"</string> <string name="mobile_data" msgid="7094582042819250762">"Farsímagögn"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Slökkt á Wi-Fi"</string> <string name="bt_is_off" msgid="2640685272289706392">"Slökkt á Bluetooth"</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index d4e6314715e9..c15e4b601222 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Frequenza multipla dual tone"</string> <string name="stream_accessibility" msgid="301136219144385106">"Accessibilità"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Suoneria"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrazione"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Disattiva audio"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tocca per riattivare l\'audio."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tocca per attivare la vibrazione. L\'audio dei servizi di accessibilità può essere disattivato."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tocca per disattivare l\'audio. L\'audio dei servizi di accessibilità può essere disattivato."</string> @@ -758,7 +761,7 @@ <string name="instant_apps" msgid="6647570248119804907">"App istantanee"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Le app istantanee non richiedono l\'installazione."</string> <string name="app_info" msgid="6856026610594615344">"Informazioni app"</string> - <string name="go_to_web" msgid="1106022723459948514">"Vai sul Web"</string> + <string name="go_to_web" msgid="2650669128861626071">"Vai al browser"</string> <string name="mobile_data" msgid="7094582042819250762">"Dati mobili"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi disattivato"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth non attivo"</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index f20275d1ca56..29271165a427 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -496,6 +496,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"טון זוגי מרובה תדרים (DTMF)"</string> <string name="stream_accessibility" msgid="301136219144385106">"נגישות"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"צלצול"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"רטט"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"השתקה"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. הקש כדי לבטל את ההשתקה."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. הקש כדי להגדיר רטט. ייתכן ששירותי הנגישות מושתקים."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. הקש כדי להשתיק. ייתכן ששירותי הנגישות מושתקים."</string> @@ -768,7 +771,7 @@ <string name="instant_apps" msgid="6647570248119804907">"אפליקציות אינסטנט"</string> <string name="instant_apps_message" msgid="8116608994995104836">"אפליקציות אינסטנט לא דורשות התקנה."</string> <string name="app_info" msgid="6856026610594615344">"פרטי אפליקציה"</string> - <string name="go_to_web" msgid="1106022723459948514">"התחבר לאינטרנט"</string> + <string name="go_to_web" msgid="2650669128861626071">"מעבר אל הדפדפן"</string> <string name="mobile_data" msgid="7094582042819250762">"נתונים סלולריים"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi כבוי"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth כבוי"</string> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index ac83c2d2e1dc..38622c95e33b 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"デュアルトーン マルチ周波数"</string> <string name="stream_accessibility" msgid="301136219144385106">"ユーザー補助機能"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"着信音"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"バイブレーション"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"ミュート"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s。タップしてミュートを解除します。"</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s。タップしてバイブレーションに設定します。ユーザー補助機能サービスがミュートされる場合があります。"</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s。タップしてミュートします。ユーザー補助機能サービスがミュートされる場合があります。"</string> @@ -758,7 +761,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Instant Apps はインストールせずに利用できます。"</string> <string name="app_info" msgid="6856026610594615344">"アプリ情報"</string> - <string name="go_to_web" msgid="1106022723459948514">"ウェブページを開く"</string> + <string name="go_to_web" msgid="2650669128861626071">"ブラウザに移動"</string> <string name="mobile_data" msgid="7094582042819250762">"モバイルデータ"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi は OFF です"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth は OFF です"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index e871c6abe9e3..933a5e312892 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"ტონალური აკრეფა"</string> <string name="stream_accessibility" msgid="301136219144385106">"მარტივი წვდომა"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"დარეკვა"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"ვიბრაცია"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"დადუმება"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. შეეხეთ დადუმების გასაუქმებლად."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. შეეხეთ ვიბრაციაზე დასაყენებლად. შეიძლება დადუმდეს მარტივი წვდომის სერვისებიც."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. შეეხეთ დასადუმებლად. შეიძლება დადუმდეს მარტივი წვდომის სერვისებიც."</string> @@ -756,8 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"მყისიერი აპები"</string> <string name="instant_apps_message" msgid="8116608994995104836">"მყისიერი აპები ინსტალაციას არ საჭიროებს."</string> <string name="app_info" msgid="6856026610594615344">"აპის შესახებ"</string> - <!-- no translation found for go_to_web (2650669128861626071) --> - <skip /> + <string name="go_to_web" msgid="2650669128861626071">"ბრაუზერზე გადასვლა"</string> <string name="mobile_data" msgid="7094582042819250762">"მობილური ინტერნეტი"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi გამორთულია"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth გამორთულია"</string> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index f2b4fc8f5a56..3f36c72feef4 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Қос үнді көп жиілік"</string> <string name="stream_accessibility" msgid="301136219144385106">"Арнайы мүмкіндіктер"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Шылдырлау"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Діріл"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Дыбысын өшіру"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Дыбысын қосу үшін түртіңіз."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Діріл режимін орнату үшін түртіңіз. Арнайы мүмкіндік қызметтерінің дыбысы өшуі мүмкін."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Дыбысын өшіру үшін түртіңіз. Арнайы мүмкіндік қызметтерінің дыбысы өшуі мүмкін."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Лездік қолданбаларды орнатудың қажеті жоқ."</string> <string name="app_info" msgid="6856026610594615344">"Қолданба ақпараты"</string> - <string name="go_to_web" msgid="1106022723459948514">"Вебке өту"</string> + <string name="go_to_web" msgid="2650669128861626071">"Браузерге өту"</string> <string name="mobile_data" msgid="7094582042819250762">"Мобильдік деректер"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi өшірулі"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth өшірулі"</string> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index ad9b05799a8b..1d5d7d4ce9af 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"ប៊្លូធូស"</string> <string name="stream_dtmf" msgid="2447177903892477915">"ហ្វ្រេកង់ពហុសំឡេងទ្វេ"</string> <string name="stream_accessibility" msgid="301136219144385106">"ភាពងាយស្រួល"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"រោទ៍"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"ញ័រ"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"បិទ"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s។ ប៉ះដើម្បីបើកសំឡេង។"</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s។ ប៉ះដើម្បីកំណត់ឲ្យញ័រ។ សេវាកម្មលទ្ធភាពប្រើប្រាស់អាចនឹងត្រូវបានបិទសំឡេង។"</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s។ ប៉ះដើម្បីបិទសំឡេង។ សេវាកម្មលទ្ធភាពប្រើប្រាស់អាចនឹងត្រូវបានបិទសំឡេង។"</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"កម្មវិធីប្រើភ្លាមៗ"</string> <string name="instant_apps_message" msgid="8116608994995104836">"កម្មវិធីប្រើភ្លាមៗមិនតម្រូវឲ្យមានការដំឡើងទេ។"</string> <string name="app_info" msgid="6856026610594615344">"ព័ត៌មានកម្មវិធី"</string> - <string name="go_to_web" msgid="1106022723459948514">"ចូលទៅកាន់បណ្តាញ"</string> + <string name="go_to_web" msgid="2650669128861626071">"ចូលទៅកម្មវិធីរុករកតាមអ៊ីនធឺណិត"</string> <string name="mobile_data" msgid="7094582042819250762">"ទិន្នន័យទូរសព្ទចល័ត"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi បានបិទ"</string> <string name="bt_is_off" msgid="2640685272289706392">"ប៊្លូធូសបានបិទ"</string> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index f4aad9648413..b2e9d8f1730d 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -492,6 +492,12 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"ಬ್ಲೂಟೂತ್"</string> <string name="stream_dtmf" msgid="2447177903892477915">"ಡ್ಯುಯಲ್ ಬಹು ಟೋನ್ ಆವರ್ತನೆ"</string> <string name="stream_accessibility" msgid="301136219144385106">"ಪ್ರವೇಶಿಸುವಿಕೆ"</string> + <!-- no translation found for volume_ringer_status_normal (4273142424125855384) --> + <skip /> + <!-- no translation found for volume_ringer_status_vibrate (1825615171021346557) --> + <skip /> + <!-- no translation found for volume_ringer_status_silent (6896394161022916369) --> + <skip /> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. ಅನ್ಮ್ಯೂಟ್ ಮಾಡುವುದಕ್ಕಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. ಕಂಪನಕ್ಕೆ ಹೊಂದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ. ಪ್ರವೇಶಿಸುವಿಕೆ ಸೇವೆಗಳನ್ನು ಮ್ಯೂಟ್ ಮಾಡಬಹುದು."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. ಮ್ಯೂಟ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ. ಪ್ರವೇಶಿಸುವಿಕೆ ಸೇವೆಗಳನ್ನು ಮ್ಯೂಟ್ ಮಾಡಬಹುದು."</string> @@ -756,7 +762,7 @@ <string name="instant_apps" msgid="6647570248119804907">"ತತ್ಕ್ಷಣ ಆಪ್ಗಳು"</string> <string name="instant_apps_message" msgid="8116608994995104836">"ತತ್ಕ್ಷಣ ಆಪ್ಗಳಿಗೆ ಸ್ಥಾಪನೆಯ ಅಗತ್ಯವಿಲ್ಲ."</string> <string name="app_info" msgid="6856026610594615344">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string> - <string name="go_to_web" msgid="1106022723459948514">"ವೆಬ್ಗೆ ಹೋಗಿ"</string> + <string name="go_to_web" msgid="2650669128861626071">"ಬ್ರೌಸರ್ಗೆ ಹೋಗಿ"</string> <string name="mobile_data" msgid="7094582042819250762">"ಮೊಬೈಲ್ ಡೇಟಾ"</string> <string name="wifi_is_off" msgid="1838559392210456893">"ವೈ-ಫೈ ಆಫ್ ಆಗಿದೆ"</string> <string name="bt_is_off" msgid="2640685272289706392">"ಬ್ಲೂಟೂತ್ ಆಫ್ ಆಗಿದೆ"</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 43d171c01a79..83018be6883d 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"블루투스"</string> <string name="stream_dtmf" msgid="2447177903892477915">"듀얼 멀티 톤 주파수"</string> <string name="stream_accessibility" msgid="301136219144385106">"접근성"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"벨소리"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"진동"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"음소거"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. 탭하여 음소거를 해제하세요."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. 탭하여 진동으로 설정하세요. 접근성 서비스가 음소거될 수 있습니다."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. 탭하여 음소거로 설정하세요. 접근성 서비스가 음소거될 수 있습니다."</string> @@ -758,7 +761,7 @@ <string name="instant_apps" msgid="6647570248119804907">"인스턴트 앱"</string> <string name="instant_apps_message" msgid="8116608994995104836">"인스턴트 앱은 설치가 필요하지 않습니다."</string> <string name="app_info" msgid="6856026610594615344">"앱 정보"</string> - <string name="go_to_web" msgid="1106022723459948514">"웹으로 이동"</string> + <string name="go_to_web" msgid="2650669128861626071">"브라우저로 이동"</string> <string name="mobile_data" msgid="7094582042819250762">"모바일 데이터"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi가 사용 중지됨"</string> <string name="bt_is_off" msgid="2640685272289706392">"블루투스가 사용 중지됨"</string> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 375d70de69ed..4aaae3c6e311 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Көп тондуу жыштык"</string> <string name="stream_accessibility" msgid="301136219144385106">"Атайын мүмкүнчүлүктөр"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Шыңгыратуу"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Дирилдөө"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Үнсүз"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Үнүн чыгаруу үчүн таптап коюңуз."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Дирилдөөгө коюу үчүн таптап коюңуз. Атайын мүмкүнчүлүктөр кызматынын үнүн өчүрүп койсо болот."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Үнүн өчүрүү үчүн таптап коюңуз. Атайын мүмкүнчүлүктөр кызматынын үнүн өчүрүп койсо болот."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Ыкчам ачылуучу колдонмолор"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Ыкчам ачылуучу колдонмолорду орнотуу талап кылынбайт."</string> <string name="app_info" msgid="6856026610594615344">"Колдонмо тууралуу"</string> - <string name="go_to_web" msgid="1106022723459948514">"Интернетке өтүү"</string> + <string name="go_to_web" msgid="2650669128861626071">"Серепчиге өтүү"</string> <string name="mobile_data" msgid="7094582042819250762">"Мобилдик Интернет"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi өчүк"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth өчүк"</string> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 064609e76f99..bc1e5b90957f 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"ບຣູທູດ"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Dual multi tone frequency"</string> <string name="stream_accessibility" msgid="301136219144385106">"ການຊ່ວຍເຂົ້າເຖິງ"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"ເຕືອນດ້ວຍສຽງ"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"ສັ່ນເຕືອນ"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"ປິດ"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. ແຕະເພື່ອເຊົາປິດສຽງ."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. ແຕະເພື່ອຕັ້ງເປັນສັ່ນ. ບໍລິການຊ່ວຍເຂົ້າເຖິງອາດຖືກປິດສຽງໄວ້."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. ແຕະເພື່ອປິດສຽງ. ບໍລິການຊ່ວຍເຂົ້າເຖິງອາດຖືກປິດສຽງໄວ້."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"ອິນສະແຕນແອັບ"</string> <string name="instant_apps_message" msgid="8116608994995104836">"ອິນສະແຕນແອັບບໍ່ຈຳເປັນຕ້ອງມີການຕິດຕັ້ງ."</string> <string name="app_info" msgid="6856026610594615344">"ຂໍ້ມູນແອັບ"</string> - <string name="go_to_web" msgid="1106022723459948514">"ໄປທີ່ເວັບ"</string> + <string name="go_to_web" msgid="2650669128861626071">"ໄປທີ່ໂປຣແກຣມທ່ອງເວັບ"</string> <string name="mobile_data" msgid="7094582042819250762">"ອິນເຕີເນັດມືຖື"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ປິດຢູ່"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ປິດຢູ່"</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index f44b930b47f7..53ddcb3ecc30 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -496,6 +496,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Dvigubas kelių tonų dažnis"</string> <string name="stream_accessibility" msgid="301136219144385106">"Pritaikymas neįgaliesiems"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Skambinti"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibruoti"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Nutildyti"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Palieskite, kad įjungtumėte garsą."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Palieskite, kad nustatytumėte vibravimą. Gali būti nutildytos pritaikymo neįgaliesiems paslaugos."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Palieskite, kad nutildytumėte. Gali būti nutildytos pritaikymo neįgaliesiems paslaugos."</string> @@ -768,7 +771,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Akimirksniu įkeliamos programėlės"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Akimirksniu įkeliamų programėlių nereikia įdiegti."</string> <string name="app_info" msgid="6856026610594615344">"Programos informacija"</string> - <string name="go_to_web" msgid="1106022723459948514">"Eiti į žiniatinklį"</string> + <string name="go_to_web" msgid="2650669128861626071">"Eiti į naršyklę"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobilieji duomenys"</string> <string name="wifi_is_off" msgid="1838559392210456893">"„Wi-Fi“ išjungtas"</string> <string name="bt_is_off" msgid="2640685272289706392">"„Bluetooth“ išjungtas"</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 8c117b3cb860..b1c3db5b7841 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Divtoņu daudzfrekvenču signalizācija"</string> <string name="stream_accessibility" msgid="301136219144385106">"Pieejamība"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Zvanīt"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrēt"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Izslēgt skaņu"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Pieskarieties, lai ieslēgtu skaņu."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Pieskarieties, lai iestatītu uz vibrozvanu. Var tikt izslēgti pieejamības pakalpojumu signāli."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Pieskarieties, lai izslēgtu skaņu. Var tikt izslēgti pieejamības pakalpojumu signāli."</string> @@ -762,7 +765,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Tūlītējās lietotnes"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Tūlītējām lietotnēm nav nepieciešama instalēšana."</string> <string name="app_info" msgid="6856026610594615344">"Lietotnes informācija"</string> - <string name="go_to_web" msgid="1106022723459948514">"Pāriet uz tīmekli"</string> + <string name="go_to_web" msgid="2650669128861626071">"Atvērt pārlūku"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobilie dati"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ir izslēgts"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ir izslēgts"</string> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 195ddec75d8f..3986e168ec59 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Двојна повеќетонска фреквенција"</string> <string name="stream_accessibility" msgid="301136219144385106">"Пристапност"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Ѕвони"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Вибрации"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Исклучи звук"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Допрете за да вклучите звук."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Допрете за да поставите на вибрации. Можеби ќе се исклучи звукот на услугите за достапност."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Допрете за да исклучите звук. Можеби ќе се исклучи звукот на услугите за достапност."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Инстант апликации"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Инстант апликациите нема потреба да се инсталираат."</string> <string name="app_info" msgid="6856026610594615344">"Информации за апликација"</string> - <string name="go_to_web" msgid="1106022723459948514">"Одете на интернет"</string> + <string name="go_to_web" msgid="2650669128861626071">"Одете на прелистувач"</string> <string name="mobile_data" msgid="7094582042819250762">"Мобилен интернет"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi е исклучено"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth е исклучен"</string> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 3eb67dfb4cac..3dfde1302b2a 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -492,6 +492,12 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"ബ്ലൂടൂത്ത്"</string> <string name="stream_dtmf" msgid="2447177903892477915">"ഡ്യുവൽ മൾട്ടി റ്റോൺ ഫ്രീക്വൻസി"</string> <string name="stream_accessibility" msgid="301136219144385106">"ഉപയോഗസഹായി"</string> + <!-- no translation found for volume_ringer_status_normal (4273142424125855384) --> + <skip /> + <!-- no translation found for volume_ringer_status_vibrate (1825615171021346557) --> + <skip /> + <!-- no translation found for volume_ringer_status_silent (6896394161022916369) --> + <skip /> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. അൺമ്യൂട്ടുചെയ്യുന്നതിന് ടാപ്പുചെയ്യുക."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. വൈബ്രേറ്റിലേക്ക് സജ്ജമാക്കുന്നതിന് ടാപ്പുചെയ്യുക. ഉപയോഗസഹായി സേവനങ്ങൾ മ്യൂട്ടുചെയ്യപ്പെട്ടേക്കാം."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. മ്യൂട്ടുചെയ്യുന്നതിന് ടാപ്പുചെയ്യുക. ഉപയോഗസഹായി സേവനങ്ങൾ മ്യൂട്ടുചെയ്യപ്പെട്ടേക്കാം."</string> @@ -756,7 +762,7 @@ <string name="instant_apps" msgid="6647570248119804907">"ഇൻസ്റ്റന്റ് ആപ്പ്"</string> <string name="instant_apps_message" msgid="8116608994995104836">"ഇൻസ്റ്റന്റ് ആപ്പിന് ഇൻസ്റ്റലേഷൻ ആവശ്യമില്ല."</string> <string name="app_info" msgid="6856026610594615344">"ആപ്പ് വിവരം"</string> - <string name="go_to_web" msgid="1106022723459948514">"വെബിൽ പോവുക"</string> + <string name="go_to_web" msgid="2650669128861626071">"ബ്രൗസറിലേക്ക് പോവുക"</string> <string name="mobile_data" msgid="7094582042819250762">"മൊബൈൽ ഡാറ്റ"</string> <string name="wifi_is_off" msgid="1838559392210456893">"വൈഫൈ ഓഫാണ്"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ഓഫാണ്"</string> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 7ecf68350f43..9f09dadc141c 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -490,6 +490,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Олон дууны давтамж"</string> <string name="stream_accessibility" msgid="301136219144385106">"Хүртээмж"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Хонх дуугаргах"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Чичиргэх"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Хаах"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Дууг нь нээхийн тулд товшино уу."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Чичиргээнд тохируулахын тулд товшино уу. Хүртээмжийн үйлчилгээний дууг хаасан."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Дууг нь хаахын тулд товшино уу. Хүртээмжийн үйлчилгээний дууг хаасан."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Шуурхай апп"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Шуурхай аппыг суулгах шаардлагагүй."</string> <string name="app_info" msgid="6856026610594615344">"Апп-н мэдээлэл"</string> - <string name="go_to_web" msgid="1106022723459948514">"Вэбэд очих"</string> + <string name="go_to_web" msgid="2650669128861626071">"Хөтчид очих"</string> <string name="mobile_data" msgid="7094582042819250762">"Мобайл дата"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi унтраалттай байна"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth унтраалттай байна"</string> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index a0c9b2c8e2f1..5b0984d68cbf 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -34,17 +34,14 @@ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचना"</string> <string name="battery_low_title" msgid="6456385927409742437">"बॅटरी कमी आहे"</string> <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> शिल्लक"</string> - <!-- no translation found for battery_low_percent_format_saver_started (7879389868952879166) --> - <skip /> + <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> शिल्लक. बॅटरी सेव्हर चालू आहे."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB चार्जिंग समर्थित नाही.\nफक्त पुरवठा केलेले चार्जर वापरा."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB चार्जिंग समर्थित नाही."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"केवळ पुरविलेले चार्जर वापरा."</string> <string name="battery_low_why" msgid="4553600287639198111">"सेटिंग्ज"</string> - <!-- no translation found for battery_saver_confirmation_title (2052100465684817154) --> - <skip /> + <string name="battery_saver_confirmation_title" msgid="2052100465684817154">"बॅटरी सेव्हर सुरू करायचा का?"</string> <string name="battery_saver_confirmation_ok" msgid="7507968430447930257">"चालू करा"</string> - <!-- no translation found for battery_saver_start_action (8187820911065797519) --> - <skip /> + <string name="battery_saver_start_action" msgid="8187820911065797519">"बॅटरी सेव्हर सुरू करा"</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"सेटिंग्ज"</string> <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"वाय-फाय"</string> <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"स्वयं-फिरणारी स्क्रीन"</string> @@ -402,11 +399,9 @@ <string name="user_remove_user_title" msgid="4681256956076895559">"वापरकर्त्यास काढायचे?"</string> <string name="user_remove_user_message" msgid="1453218013959498039">"या वापरकर्त्याचे सर्व अॅप्स आणि डेटा काढून टाकला जाईल."</string> <string name="user_remove_user_remove" msgid="7479275741742178297">"काढा"</string> - <!-- no translation found for battery_saver_notification_title (8614079794522291840) --> - <skip /> + <string name="battery_saver_notification_title" msgid="8614079794522291840">"बॅटरी सेव्हर चालू आहे"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"कामगिरी आणि पार्श्वभूमीवरील डेटा कमी करते"</string> - <!-- no translation found for battery_saver_notification_action_text (132118784269455533) --> - <skip /> + <string name="battery_saver_notification_action_text" msgid="132118784269455533">"बॅटरी सेव्हर बंद करा"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> आपल्या स्क्रीनवर प्रदर्शित होणारी प्रत्येक गोष्ट कॅप्चर करणे प्रारंभ करेल."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"पुन्हा दर्शवू नका"</string> <string name="clear_all_notifications_text" msgid="814192889771462828">"सर्व साफ करा"</string> @@ -497,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"ब्लूटूथ"</string> <string name="stream_dtmf" msgid="2447177903892477915">"दुहेरी एकाधिक टोन वारंंवारता"</string> <string name="stream_accessibility" msgid="301136219144385106">"प्रवेशयोग्यता"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"रिंग करा"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"कंपन"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"म्युट करा"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. सशब्द करण्यासाठी टॅप करा."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. कंपन सेट करण्यासाठी टॅप करा. प्रवेशयोग्यता सेवा नि:शब्द केल्या जाऊ शकतात."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. नि:शब्द करण्यासाठी टॅप करा. प्रवेशक्षमता सेवा नि:शब्द केल्या जाऊ शकतात."</string> @@ -761,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"इन्सटंट अॅप्स"</string> <string name="instant_apps_message" msgid="8116608994995104836">"इन्सटंट अॅप्सना स्थापनेची आवश्यकता नसते."</string> <string name="app_info" msgid="6856026610594615344">"अॅप माहिती"</string> - <string name="go_to_web" msgid="1106022723459948514">"वेबवर जा"</string> + <string name="go_to_web" msgid="2650669128861626071">"ब्राउझरवर जा"</string> <string name="mobile_data" msgid="7094582042819250762">"मोबाइल डेटा"</string> <string name="wifi_is_off" msgid="1838559392210456893">"वाय-फाय बंद आहे"</string> <string name="bt_is_off" msgid="2640685272289706392">"ब्लूटूथ बंद आहे"</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 78708f7d6251..2907761fc749 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Multifrekuensi dwinada"</string> <string name="stream_accessibility" msgid="301136219144385106">"Kebolehaksesan"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Dering"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Getar"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Redam"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Ketik untuk menyahredam."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Ketik untuk menetapkan pada getar. Perkhidmatan kebolehaksesan mungkin diredamkan."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Ketik untuk meredam. Perkhidmatan kebolehaksesan mungkin diredamkan."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Apl Segera"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Apl segera tidak memerlukan pemasangan."</string> <string name="app_info" msgid="6856026610594615344">"Maklumat apl"</string> - <string name="go_to_web" msgid="1106022723459948514">"Pergi ke web"</string> + <string name="go_to_web" msgid="2650669128861626071">"Pergi ke penyemak imbas"</string> <string name="mobile_data" msgid="7094582042819250762">"Data mudah alih"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi dimatikan"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth dimatikan"</string> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index a3ec0db8a3d5..22375b4322e9 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"ဘလူးတုသ်"</string> <string name="stream_dtmf" msgid="2447177903892477915">"နှစ်လိုင်းပေါင်း အသံပေါင်းစုံ ကြိမ်နှုန်း"</string> <string name="stream_accessibility" msgid="301136219144385106">"အများသုံးစွဲနိုင်မှု"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"အသံမြည်သည်"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"တုန်ခါသည်"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"အသံတိတ်သည်"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s။ အသံပြန်ဖွင့်ရန် တို့ပါ။"</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s။ တုန်ခါမှုကို သတ်မှတ်ရန် တို့ပါ။ အများသုံးစွဲနိုင်မှု ဝန်ဆောင်မှုများကို အသံပိတ်ထားနိုင်ပါသည်။"</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s။ အသံပိတ်ရန် တို့ပါ။ အများသုံးစွဲနိုင်မှု ဝန်ဆောင်မှုများကို အသံပိတ်ထားနိုင်ပါသည်။"</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string> <string name="instant_apps_message" msgid="8116608994995104836">"ချက်ခြင်းသုံးအက်ပ်များကို ထည့်သွင်းစရာမလိုပါ။"</string> <string name="app_info" msgid="6856026610594615344">"အက်ပ်အချက်အလက်"</string> - <string name="go_to_web" msgid="1106022723459948514">"ဝဘ်သို့ သွားရန်"</string> + <string name="go_to_web" msgid="2650669128861626071">"ဘရောင်ဇာသို့ သွားပါ"</string> <string name="mobile_data" msgid="7094582042819250762">"မိုဘိုင်းဒေတာ"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ကို ပိတ်ထားသည်"</string> <string name="bt_is_off" msgid="2640685272289706392">"ဘလူးတုသ်ကို ပိတ်ထားသည်"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index bebfad541236..51b3b0d6ddf3 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"DTMF (dual-tone multi-frequency)"</string> <string name="stream_accessibility" msgid="301136219144385106">"Tilgjengelighet"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Ring"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrer"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Ignorer"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Trykk for å slå på lyden."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Trykk for å angi vibrasjon. Lyden kan bli slått av for tilgjengelighetstjenestene."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Trykk for å slå av lyden. Lyden kan bli slått av for tilgjengelighetstjenestene."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Du trenger ikke å installere instant-apper."</string> <string name="app_info" msgid="6856026610594615344">"Info om appen"</string> - <string name="go_to_web" msgid="1106022723459948514">"Gå til nettstedet"</string> + <string name="go_to_web" msgid="2650669128861626071">"Gå til nettleser"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobildata"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi er av"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth er av"</string> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index bfe8f07fe817..0a63ce2177b7 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"ब्लुटुथ"</string> <string name="stream_dtmf" msgid="2447177903892477915">"दोहोरो बहु टोनको फ्रिक्वेन्सी"</string> <string name="stream_accessibility" msgid="301136219144385106">"पहुँच"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"घन्टी"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"कम्पन"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"म्युट गर्नुहोस्"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s। अनम्यूट गर्नका लागि ट्याप गर्नुहोस्।"</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s। कम्पनमा सेट गर्नका लागि ट्याप गर्नुहोस्। पहुँच सम्बन्धी सेवाहरू म्यूट हुन सक्छन्।"</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s। म्यूट गर्नका लागि ट्याप गर्नुहोस्। पहुँच सम्बन्धी सेवाहरू म्यूट हुन सक्छन्।"</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"तात्कालिक अनुप्रयोगहरू"</string> <string name="instant_apps_message" msgid="8116608994995104836">"तात्कालिक अनुप्रयोगहरूलाई स्थापना गर्नु पर्दैन|"</string> <string name="app_info" msgid="6856026610594615344">"अनुप्रयोगका बारे जानकारी"</string> - <string name="go_to_web" msgid="1106022723459948514">"वेबमा जानुहोस्"</string> + <string name="go_to_web" msgid="2650669128861626071">"ब्राउजरमा जानुहोस्"</string> <string name="mobile_data" msgid="7094582042819250762">"मोबाइल डेटा"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi‑Fi निष्क्रिय छ"</string> <string name="bt_is_off" msgid="2640685272289706392">"ब्लुटुथ निष्क्रिय छ"</string> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 98ad14fe3f06..ca0fa073aea2 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Frequentie voor tweevoudige multitoon"</string> <string name="stream_accessibility" msgid="301136219144385106">"Toegankelijkheid"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Bellen"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Trillen"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Dempen"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tik om dempen op te heffen."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tik om in te stellen op trillen. Toegankelijkheidsservices kunnen zijn gedempt."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tik om te dempen. Toegankelijkheidsservices kunnen zijn gedempt."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Instant-apps"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Instant-apps hoeven niet te worden geïnstalleerd."</string> <string name="app_info" msgid="6856026610594615344">"App-info"</string> - <string name="go_to_web" msgid="1106022723459948514">"Ga naar internet"</string> + <string name="go_to_web" msgid="2650669128861626071">"Ga naar browser"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobiele data"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wifi is uitgeschakeld"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is uitgeschakeld"</string> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 870629869c22..c6475dcc361b 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -34,17 +34,14 @@ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ਸੂਚਨਾਵਾਂ"</string> <string name="battery_low_title" msgid="6456385927409742437">"ਬੈਟਰੀ ਘੱਟ ਹੈ"</string> <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ਬਾਕੀ"</string> - <!-- no translation found for battery_low_percent_format_saver_started (7879389868952879166) --> - <skip /> + <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> ਬਾਕੀ। ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਹੈ।"</string> <string name="invalid_charger" msgid="4549105996740522523">"USB ਚਾਰਜਿੰਗ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ।\nਕੇਵਲ ਸਪਲਾਈ ਕੀਤਾ ਚਾਰਜਰ ਵਰਤੋ।"</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB ਚਾਰਜਿੰਗ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ।"</string> <string name="invalid_charger_text" msgid="5474997287953892710">"ਕੇਵਲ ਸਪਲਾਈ ਕੀਤਾ ਚਾਰਜਰ ਵਰਤੋ।"</string> <string name="battery_low_why" msgid="4553600287639198111">"ਸੈਟਿੰਗਾਂ"</string> - <!-- no translation found for battery_saver_confirmation_title (2052100465684817154) --> - <skip /> + <string name="battery_saver_confirmation_title" msgid="2052100465684817154">"ਕੀ ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਕਰਨਾ ਹੈ?"</string> <string name="battery_saver_confirmation_ok" msgid="7507968430447930257">"ਚਾਲੂ ਕਰੋ"</string> - <!-- no translation found for battery_saver_start_action (8187820911065797519) --> - <skip /> + <string name="battery_saver_start_action" msgid="8187820911065797519">"ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਕਰੋ"</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"ਸੈਟਿੰਗਾਂ"</string> <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"ਵਾਈ-ਫਾਈ"</string> <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"ਸਕ੍ਰੀਨ ਆਪਣੇ-ਆਪ ਘੁੰਮਾਓ"</string> @@ -402,11 +399,9 @@ <string name="user_remove_user_title" msgid="4681256956076895559">"ਕੀ ਵਰਤੋਂਕਾਰ ਹਟਾਉਣਾ ਹੈ?"</string> <string name="user_remove_user_message" msgid="1453218013959498039">"ਇਸ ਉਪਭੋਗਤਾ ਦੇ ਸਾਰੇ ਐਪਸ ਅਤੇ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਏਗਾ।"</string> <string name="user_remove_user_remove" msgid="7479275741742178297">"ਹਟਾਓ"</string> - <!-- no translation found for battery_saver_notification_title (8614079794522291840) --> - <skip /> + <string name="battery_saver_notification_title" msgid="8614079794522291840">"ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਹੈ"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"ਪ੍ਰਦਰਸ਼ਨ ਅਤੇ ਪਿਛੋਕੜ ਡਾਟਾ ਘੱਟ ਕਰਦਾ ਹੈ"</string> - <!-- no translation found for battery_saver_notification_action_text (132118784269455533) --> - <skip /> + <string name="battery_saver_notification_action_text" msgid="132118784269455533">"ਬੈਟਰੀ ਸੇਵਰ ਬੰਦ ਕਰੋ"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਉਹ ਸਭ ਕੁਝ ਕੈਪਚਰ ਕਰਨਾ ਸ਼ੁਰੂ ਕਰ ਦੇਵੇਗਾ, ਜੋ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ ਤੇ ਡਿਸਪਲੇ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"ਦੁਬਾਰਾ ਨਾ ਦਿਖਾਓ"</string> <string name="clear_all_notifications_text" msgid="814192889771462828">"ਸਭ ਕਲੀਅਰ ਕਰੋ"</string> @@ -497,6 +492,12 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"ਬਲੂਟੁੱਥ"</string> <string name="stream_dtmf" msgid="2447177903892477915">"ਦੂਹਰੀ ਮਲਟੀ ਟੋਨ ਆਵਰਤੀ"</string> <string name="stream_accessibility" msgid="301136219144385106">"ਪਹੁੰਚਯੋਗਤਾ"</string> + <!-- no translation found for volume_ringer_status_normal (4273142424125855384) --> + <skip /> + <!-- no translation found for volume_ringer_status_vibrate (1825615171021346557) --> + <skip /> + <!-- no translation found for volume_ringer_status_silent (6896394161022916369) --> + <skip /> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s। ਅਣਮਿਊਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s। ਥਰਥਰਾਹਟ ਸੈੱਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ। ਪਹੁੰਚਯੋਗਤਾ ਸੇਵਾਵਾਂ ਮਿਊਟ ਹੋ ਸਕਦੀਆਂ ਹਨ।"</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s। ਮਿਊਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ। ਪਹੁੰਚਯੋਗਤਾ ਸੇਵਾਵਾਂ ਮਿਊਟ ਹੋ ਸਕਦੀਆਂ ਹਨ।"</string> @@ -761,7 +762,7 @@ <string name="instant_apps" msgid="6647570248119804907">"ਤਤਕਾਲ ਐਪਾਂ"</string> <string name="instant_apps_message" msgid="8116608994995104836">"ਤਤਕਾਲ ਐਪਾਂ ਨੂੰ ਸਥਾਪਨਾ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ।"</string> <string name="app_info" msgid="6856026610594615344">"ਐਪ ਜਾਣਕਾਰੀ"</string> - <string name="go_to_web" msgid="1106022723459948514">"ਵੈੱਬ \'ਤੇ ਜਾਓ"</string> + <string name="go_to_web" msgid="2650669128861626071">"ਬ੍ਰਾਊਜ਼ਰ \'ਤੇ ਜਾਓ"</string> <string name="mobile_data" msgid="7094582042819250762">"ਮੋਬਾਈਲ ਡਾਟਾ"</string> <string name="wifi_is_off" msgid="1838559392210456893">"ਵਾਈ-ਫਾਈ ਬੰਦ ਹੈ"</string> <string name="bt_is_off" msgid="2640685272289706392">"ਬਲੂਟੁੱਥ ਬੰਦ ਹੈ"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 56a8e599115c..bc2a9545e526 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -496,6 +496,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"DTMF"</string> <string name="stream_accessibility" msgid="301136219144385106">"Ułatwienia dostępu"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Dzwonek"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Wibracje"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Wyciszenie"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Kliknij, by wyłączyć wyciszenie."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Kliknij, by włączyć wibracje. Ułatwienia dostępu mogą być wyciszone."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Kliknij, by wyciszyć. Ułatwienia dostępu mogą być wyciszone."</string> @@ -768,7 +771,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Aplikacje błyskawiczne"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Aplikacji błyskawicznych nie trzeba instalować."</string> <string name="app_info" msgid="6856026610594615344">"O aplikacji"</string> - <string name="go_to_web" msgid="1106022723459948514">"Wejdź na stronę internetową"</string> + <string name="go_to_web" msgid="2650669128861626071">"Otwórz przeglądarkę"</string> <string name="mobile_data" msgid="7094582042819250762">"Komórkowa transmisja danych"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi jest wyłączone"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth jest wyłączony"</string> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index a7c3af123393..61aa901f90e6 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Multifrequência de dois tons"</string> <string name="stream_accessibility" msgid="301136219144385106">"Acessibilidade"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Tocar"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrar"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Ignorar"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Toque para ativar o som."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Toque para configurar para vibrar. É possível que os serviços de acessibilidade sejam silenciados."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Toque para silenciar. É possível que os serviços de acessibilidade sejam silenciados."</string> @@ -758,7 +761,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Os Instant Apps não requerem instalação."</string> <string name="app_info" msgid="6856026610594615344">"Informações do app"</string> - <string name="go_to_web" msgid="1106022723459948514">"Acessar a Web"</string> + <string name="go_to_web" msgid="2650669128861626071">"Abrir o navegador"</string> <string name="mobile_data" msgid="7094582042819250762">"Dados móveis"</string> <string name="wifi_is_off" msgid="1838559392210456893">"O Wi-Fi está desativado"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desativado"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index b5b3475b6ca1..7f2c6435612f 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Multifrequência de duas tonalidades"</string> <string name="stream_accessibility" msgid="301136219144385106">"Acessibilidade"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Toque"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrar"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Desativar som"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Toque para reativar o som."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Toque para ativar a vibração. Os serviços de acessibilidade podem ser silenciados."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Toque para desativar o som. Os serviços de acessibilidade podem ser silenciados."</string> @@ -756,8 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Aplicações instantâneas"</string> <string name="instant_apps_message" msgid="8116608994995104836">"As Aplicações instantâneas não requerem instalação."</string> <string name="app_info" msgid="6856026610594615344">"Informações da aplicação"</string> - <!-- no translation found for go_to_web (2650669128861626071) --> - <skip /> + <string name="go_to_web" msgid="2650669128861626071">"Ir para o navegador"</string> <string name="mobile_data" msgid="7094582042819250762">"Dados móveis"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi desativado"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desativado"</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index a7c3af123393..61aa901f90e6 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Multifrequência de dois tons"</string> <string name="stream_accessibility" msgid="301136219144385106">"Acessibilidade"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Tocar"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrar"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Ignorar"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Toque para ativar o som."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Toque para configurar para vibrar. É possível que os serviços de acessibilidade sejam silenciados."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Toque para silenciar. É possível que os serviços de acessibilidade sejam silenciados."</string> @@ -758,7 +761,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Os Instant Apps não requerem instalação."</string> <string name="app_info" msgid="6856026610594615344">"Informações do app"</string> - <string name="go_to_web" msgid="1106022723459948514">"Acessar a Web"</string> + <string name="go_to_web" msgid="2650669128861626071">"Abrir o navegador"</string> <string name="mobile_data" msgid="7094582042819250762">"Dados móveis"</string> <string name="wifi_is_off" msgid="1838559392210456893">"O Wi-Fi está desativado"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desativado"</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 4392efe88f32..21084556050a 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -496,6 +496,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Frecvență tonuri multiple duale"</string> <string name="stream_accessibility" msgid="301136219144385106">"Accesibilitate"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Sonerie"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrații"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Blocați"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Atingeți pentru a activa sunetul."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Atingeți pentru a seta vibrarea. Sunetul se poate dezactiva pentru serviciile de accesibilitate."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Atingeți pentru a dezactiva sunetul. Sunetul se poate dezactiva pentru serviciile de accesibilitate."</string> @@ -764,7 +767,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Aplicații instantanee"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Aplicațiile instantanee nu necesită instalare."</string> <string name="app_info" msgid="6856026610594615344">"Informații despre aplicație"</string> - <string name="go_to_web" msgid="1106022723459948514">"Accesați pe web"</string> + <string name="go_to_web" msgid="2650669128861626071">"Accesați browserul"</string> <string name="mobile_data" msgid="7094582042819250762">"Date mobile"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Conexiunea Wi-Fi este dezactivată"</string> <string name="bt_is_off" msgid="2640685272289706392">"Funcția Bluetooth este dezactivată"</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index fd1d3be536a4..ac4f5fec55f2 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -498,6 +498,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Тональный набор"</string> <string name="stream_accessibility" msgid="301136219144385106">"Специальные возможности"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Со звуком"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Вибрация"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Без звука"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Нажмите, чтобы включить звук."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Нажмите, чтобы включить вибрацию. Специальные возможности могут прекратить работу."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Нажмите, чтобы выключить звук. Специальные возможности могут прекратить работу."</string> @@ -770,7 +773,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Приложения с мгновенным запуском"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Приложения с мгновенным запуском не требуется устанавливать."</string> <string name="app_info" msgid="6856026610594615344">"О приложении"</string> - <string name="go_to_web" msgid="1106022723459948514">"Перейти в браузер"</string> + <string name="go_to_web" msgid="2650669128861626071">"Перейти в браузер"</string> <string name="mobile_data" msgid="7094582042819250762">"Моб. Интернет"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Модуль Wi-Fi отключен"</string> <string name="bt_is_off" msgid="2640685272289706392">"Модуль Bluetooth отключен"</string> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index fd636ad47235..12f4838f1cb2 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"බ්ලූටූත්"</string> <string name="stream_dtmf" msgid="2447177903892477915">"ද්විත්ව බහු ස්වර සංඛ්යාතය"</string> <string name="stream_accessibility" msgid="301136219144385106">"ප්රවේශ්යතාව"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"නාද කරන්න"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"කම්පනය කරන්න"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"නිහඬ කරන්න"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. නිහඬ කිරීම ඉවත් කිරීමට තට්ටු කරන්න."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. කම්පනය කිරීමට තට්ටු කරන්න. ප්රවේශ්යතා සේවා නිහඬ කළ හැකිය."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. නිහඬ කිරීමට තට්ටු කරන්න. ප්රවේශ්යතා සේවා නිහඬ කළ හැකිය."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"ක්ෂණික යෙදුම්"</string> <string name="instant_apps_message" msgid="8116608994995104836">"ක්ෂණික යෙදුම් ස්ථාපනය කිරීම අවශ්ය නොවේ."</string> <string name="app_info" msgid="6856026610594615344">"යෙදුම් තොරතුරු"</string> - <string name="go_to_web" msgid="1106022723459948514">"වෙබය වෙත යන්න"</string> + <string name="go_to_web" msgid="2650669128861626071">"බ්රවුසරය වෙත යන්න"</string> <string name="mobile_data" msgid="7094582042819250762">"ජංගම දත්ත"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ක්රියා විරහිතයි"</string> <string name="bt_is_off" msgid="2640685272289706392">"බ්ලූටූත් ක්රියා විරහිතයි"</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index b7f54450176c..151c2b4e78b7 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -498,6 +498,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Dvojtónová multifrekvencia"</string> <string name="stream_accessibility" msgid="301136219144385106">"Dostupnosť"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Prezvoniť"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrovať"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Vypnúť zvuk"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Klepnutím zapnite zvuk."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Klepnutím aktivujte režim vibrovania. Služby dostupnosti je možné stlmiť."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Klepnutím vypnite zvuk. Služby dostupnosti je možné stlmiť."</string> @@ -770,7 +773,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Okamžité aplikácie"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Okamžité aplikácie nevyžadujú inštaláciu."</string> <string name="app_info" msgid="6856026610594615344">"Info o aplikácii"</string> - <string name="go_to_web" msgid="1106022723459948514">"Prejsť na internet"</string> + <string name="go_to_web" msgid="2650669128861626071">"Otvoriť prehliadač"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobilné dáta"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Pripojenie Wi‑Fi je vypnuté"</string> <string name="bt_is_off" msgid="2640685272289706392">"Rozhranie Bluetooth je vypnuté"</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 5a00c5355b8c..ee628e121636 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -498,6 +498,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Dvojna večtonska frekvenca"</string> <string name="stream_accessibility" msgid="301136219144385106">"Funkcije za ljudi s posebnimi potrebami"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Zvonjenje"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibriranje"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Utišano"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Dotaknite se, če želite vklopiti zvok."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Dotaknite se, če želite nastaviti vibriranje. V storitvah za ljudi s posebnimi potrebami bo morda izklopljen zvok."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Dotaknite se, če želite izklopiti zvok. V storitvah za ljudi s posebnimi potrebami bo morda izklopljen zvok."</string> @@ -770,7 +773,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Nenamestljive aplikacije"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Nenamestljivih aplikacij ni treba namestiti."</string> <string name="app_info" msgid="6856026610594615344">"Podatki o aplikaciji"</string> - <string name="go_to_web" msgid="1106022723459948514">"Pojdi v splet"</string> + <string name="go_to_web" msgid="2650669128861626071">"Odpri brskalnik"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobilni podatki"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je izklopljen"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je izklopljen"</string> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index 801ee90c0c1a..7641e6c6d29f 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Frekuenca e dyfishtë me shumë tone"</string> <string name="stream_accessibility" msgid="301136219144385106">"Qasshmëria"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Bjeri ziles"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Dridhje"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Pa zë"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Trokit për të aktivizuar."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Trokit për ta caktuar te dridhja. Shërbimet e qasshmërisë mund të çaktivizohen."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Trokit për të çaktivizuar. Shërbimet e qasshmërisë mund të çaktivizohen."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Aplikacionet e çastit"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Aplikacionet e çastit nuk kërkojnë instalim."</string> <string name="app_info" msgid="6856026610594615344">"Informacioni mbi aplikacionin"</string> - <string name="go_to_web" msgid="1106022723459948514">"Shko në ueb"</string> + <string name="go_to_web" msgid="2650669128861626071">"Shko te shfletuesi"</string> <string name="mobile_data" msgid="7094582042819250762">"Të dhënat celulare"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi është joaktiv"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth-i është joaktiv"</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 7a76d4002f30..b5fab0d76028 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Вишеструка фреквенција дуалног тона"</string> <string name="stream_accessibility" msgid="301136219144385106">"Приступачност"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Активирај звоно"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Вибрирај"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Искључи звук"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Додирните да бисте укључили звук."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Додирните да бисте подесили на вибрацију. Звук услуга приступачности ће можда бити искључен."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Додирните да бисте искључили звук. Звук услуга приступачности ће можда бити искључен."</string> @@ -762,7 +765,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Инстант апликације"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Инстант апликације не захтевају инсталацију."</string> <string name="app_info" msgid="6856026610594615344">"Информације о апликацији"</string> - <string name="go_to_web" msgid="1106022723459948514">"Иди на веб"</string> + <string name="go_to_web" msgid="2650669128861626071">"Иди на прегледач"</string> <string name="mobile_data" msgid="7094582042819250762">"Мобилни подаци"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi је искључен"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth је искључен"</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 9b978e2ff2b7..cc6f542a0b2c 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Tonval"</string> <string name="stream_accessibility" msgid="301136219144385106">"Tillgänglighet"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Ringsignal"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibration"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Dölj"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tryck här om du vill slå på ljudet."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tryck här om du vill sätta på vibrationen. Tillgänglighetstjänster kanske inaktiveras."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tryck här om du vill stänga av ljudet. Tillgänglighetstjänsterna kanske inaktiveras."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Snabbappar behöver inte installeras."</string> <string name="app_info" msgid="6856026610594615344">"Info om appen"</string> - <string name="go_to_web" msgid="1106022723459948514">"Öppna webbplatsen"</string> + <string name="go_to_web" msgid="2650669128861626071">"Öppna webbläsaren"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobildata"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi är inaktiverat"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth är inaktiverat"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index aa7c3f72aff8..b83f10f24819 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Masafa ya ishara ya kampuni ya simu"</string> <string name="stream_accessibility" msgid="301136219144385106">"Zana za walio na matatizo ya kuona au kusikia"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Piga"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Tetema"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Zima sauti"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Gusa ili urejeshe."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Gusa ili uweke mtetemo. Huenda ikakomesha huduma za zana za walio na matatizo ya kuona au kusikia."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Gusa ili ukomeshe. Huenda ikakomesha huduma za zana za walio na matatizo ya kuona au kusikia."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Programu Zinazofunguka Papo Hapo"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Huhitaji kusakinisha programu zinazofunguka papo hapo."</string> <string name="app_info" msgid="6856026610594615344">"Maelezo ya programu"</string> - <string name="go_to_web" msgid="1106022723459948514">"Nenda kwenye wavuti"</string> + <string name="go_to_web" msgid="2650669128861626071">"Tumia kivinjari"</string> <string name="mobile_data" msgid="7094582042819250762">"Data ya mtandao wa simu"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi imezimwa"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth imezimwa"</string> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 4278d3683088..9d532e27e67a 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -34,17 +34,14 @@ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"அறிவிப்புகள்"</string> <string name="battery_low_title" msgid="6456385927409742437">"பேட்டரி குறைவு"</string> <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> உள்ளது"</string> - <!-- no translation found for battery_low_percent_format_saver_started (7879389868952879166) --> - <skip /> + <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> மீதமுள்ளது. பேட்டரி சேமிப்பான் ஆன் செய்யப்பட்டுள்ளது."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB மூலம் சார்ஜ் செய்வது ஆதரிக்கப்படவில்லை.\nவழங்கப்பட்ட சார்ஜரை மட்டும் பயன்படுத்தவும்."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB சார்ஜிங் ஆதரிக்கப்படவில்லை."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"வழங்கப்பட்ட சார்ஜரை மட்டும் பயன்படுத்துக."</string> <string name="battery_low_why" msgid="4553600287639198111">"அமைப்பு"</string> - <!-- no translation found for battery_saver_confirmation_title (2052100465684817154) --> - <skip /> + <string name="battery_saver_confirmation_title" msgid="2052100465684817154">"பேட்டரி சேமிப்பானை ஆன் செய்யவா?"</string> <string name="battery_saver_confirmation_ok" msgid="7507968430447930257">"இயக்கு"</string> - <!-- no translation found for battery_saver_start_action (8187820911065797519) --> - <skip /> + <string name="battery_saver_start_action" msgid="8187820911065797519">"பேட்டரி சேமிப்பானை ஆன் செய்"</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"அமைப்பு"</string> <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"வைஃபை"</string> <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"திரையைத் தானாகச் சுழற்று"</string> @@ -402,11 +399,9 @@ <string name="user_remove_user_title" msgid="4681256956076895559">"பயனரை அகற்றவா?"</string> <string name="user_remove_user_message" msgid="1453218013959498039">"இந்தப் பயனரின் எல்லா பயன்பாடுகளும் தரவும் நீக்கப்படும்."</string> <string name="user_remove_user_remove" msgid="7479275741742178297">"அகற்று"</string> - <!-- no translation found for battery_saver_notification_title (8614079794522291840) --> - <skip /> + <string name="battery_saver_notification_title" msgid="8614079794522291840">"பேட்டரி சேமிப்பான் ஆன் செய்யப்பட்டுள்ளது"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"செயல்திறனையும் பின்புலத் தரவையும் குறைக்கிறது"</string> - <!-- no translation found for battery_saver_notification_action_text (132118784269455533) --> - <skip /> + <string name="battery_saver_notification_action_text" msgid="132118784269455533">"பேட்டரி சேமிப்பானை ஆஃப் செய்"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"திரையில் காட்டப்படும் அனைத்தையும் <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> படமெடுக்கும்."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"மீண்டும் காட்டாதே"</string> <string name="clear_all_notifications_text" msgid="814192889771462828">"எல்லாவற்றையும் அழி"</string> @@ -497,6 +492,12 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"புளூடூத்"</string> <string name="stream_dtmf" msgid="2447177903892477915">"டூயல் டோன் மல்டி ஃப்ரீக்வென்சி"</string> <string name="stream_accessibility" msgid="301136219144385106">"அணுகல்தன்மை"</string> + <!-- no translation found for volume_ringer_status_normal (4273142424125855384) --> + <skip /> + <!-- no translation found for volume_ringer_status_vibrate (1825615171021346557) --> + <skip /> + <!-- no translation found for volume_ringer_status_silent (6896394161022916369) --> + <skip /> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. ஒலி இயக்க, தட்டவும்."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. அதிர்விற்கு அமைக்க, தட்டவும். அணுகல்தன்மை சேவைகள் ஒலியடக்கப்படக்கூடும்."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. ஒலியடக்க, தட்டவும். அணுகல்தன்மை சேவைகள் ஒலியடக்கப்படக்கூடும்."</string> @@ -761,7 +762,7 @@ <string name="instant_apps" msgid="6647570248119804907">"இன்ஸ்டண்ட் பயன்பாடுகள்"</string> <string name="instant_apps_message" msgid="8116608994995104836">"இன்ஸ்டண்ட் பயன்பாடுகளுக்கு நிறுவல் தேவையில்லை."</string> <string name="app_info" msgid="6856026610594615344">"ஆப்ஸ் தகவல்"</string> - <string name="go_to_web" msgid="1106022723459948514">"இணையத்திற்குச் செல்"</string> + <string name="go_to_web" msgid="2650669128861626071">"உலாவிக்குக்குச் செல்"</string> <string name="mobile_data" msgid="7094582042819250762">"மொபைல் டேட்டா"</string> <string name="wifi_is_off" msgid="1838559392210456893">"வைஃபை முடக்கத்தில் உள்ளது"</string> <string name="bt_is_off" msgid="2640685272289706392">"புளூடூத் முடக்கத்தில் உள்ளது"</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 60fe59a232c0..f1c66f5c942d 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -34,17 +34,14 @@ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"నోటిఫికేషన్లు"</string> <string name="battery_low_title" msgid="6456385927409742437">"బ్యాటరీ తక్కువగా ఉంది"</string> <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> మిగిలి ఉంది"</string> - <!-- no translation found for battery_low_percent_format_saver_started (7879389868952879166) --> - <skip /> + <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> మిగిలి ఉంది. బ్యాటరీ సేవర్ ఆన్లో ఉంది."</string> <string name="invalid_charger" msgid="4549105996740522523">"USB ఛార్జింగ్కు మద్దతు లేదు.\nఅందించిన ఛార్జర్ను మాత్రమే ఉపయోగించండి."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB ఛార్జింగ్కి మద్దతు లేదు."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"అందించిన ఛార్జర్ను మాత్రమే ఉపయోగించండి."</string> <string name="battery_low_why" msgid="4553600287639198111">"సెట్టింగ్లు"</string> - <!-- no translation found for battery_saver_confirmation_title (2052100465684817154) --> - <skip /> + <string name="battery_saver_confirmation_title" msgid="2052100465684817154">"బ్యాటరీ సేవర్ను ఆన్ చేయాలా?"</string> <string name="battery_saver_confirmation_ok" msgid="7507968430447930257">"ఆన్ చేయి"</string> - <!-- no translation found for battery_saver_start_action (8187820911065797519) --> - <skip /> + <string name="battery_saver_start_action" msgid="8187820911065797519">"బ్యాటరీ సేవర్ను ఆన్ చేయండి"</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"సెట్టింగ్లు"</string> <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string> <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"స్క్రీన్ను స్వయంచాలకంగా తిప్పండి"</string> @@ -402,11 +399,9 @@ <string name="user_remove_user_title" msgid="4681256956076895559">"వినియోగదారుని తీసివేయాలా?"</string> <string name="user_remove_user_message" msgid="1453218013959498039">"ఈ వినియోగదారుకు సంబంధించిన అన్ని అనువర్తనాలు మరియు డేటా తొలగించబడతాయి."</string> <string name="user_remove_user_remove" msgid="7479275741742178297">"తీసివేయి"</string> - <!-- no translation found for battery_saver_notification_title (8614079794522291840) --> - <skip /> + <string name="battery_saver_notification_title" msgid="8614079794522291840">"బ్యాటరీ సేవర్ ఆన్లో ఉంది"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"పనితీరుని మరియు నేపథ్య డేటాను తగ్గిస్తుంది"</string> - <!-- no translation found for battery_saver_notification_action_text (132118784269455533) --> - <skip /> + <string name="battery_saver_notification_action_text" msgid="132118784269455533">"బ్యాటరీ సేవర్ను ఆఫ్ చేయండి"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> మీ స్క్రీన్పై కనిపించే ప్రతిదాన్ని క్యాప్చర్ చేయడం ప్రారంభిస్తుంది."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"మళ్లీ చూపవద్దు"</string> <string name="clear_all_notifications_text" msgid="814192889771462828">"అన్నీ క్లియర్ చేయండి"</string> @@ -497,6 +492,12 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"బ్లూటూత్"</string> <string name="stream_dtmf" msgid="2447177903892477915">"డ్యూయల్ మల్టీ టోన్ ఫ్రీక్వెన్సీ"</string> <string name="stream_accessibility" msgid="301136219144385106">"యాక్సెస్ సామర్థ్యం"</string> + <!-- no translation found for volume_ringer_status_normal (4273142424125855384) --> + <skip /> + <!-- no translation found for volume_ringer_status_vibrate (1825615171021346557) --> + <skip /> + <!-- no translation found for volume_ringer_status_silent (6896394161022916369) --> + <skip /> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. అన్మ్యూట్ చేయడానికి నొక్కండి."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. వైబ్రేషన్కు సెట్ చేయడానికి నొక్కండి. యాక్సెస్ సామర్థ్య సేవలు మ్యూట్ చేయబడవచ్చు."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. మ్యూట్ చేయడానికి నొక్కండి. యాక్సెస్ సామర్థ్య సేవలు మ్యూట్ చేయబడవచ్చు."</string> @@ -761,7 +762,7 @@ <string name="instant_apps" msgid="6647570248119804907">"తక్షణ అనువర్తనాలు"</string> <string name="instant_apps_message" msgid="8116608994995104836">"తక్షణ అనువర్తనాలకు ఇన్స్టాలేషన్ అవసరం లేదు."</string> <string name="app_info" msgid="6856026610594615344">"యాప్ సమాచారం"</string> - <string name="go_to_web" msgid="1106022723459948514">"వెబ్కు వెళ్లు"</string> + <string name="go_to_web" msgid="2650669128861626071">"బ్రౌజర్కు వెళ్లండి"</string> <string name="mobile_data" msgid="7094582042819250762">"మొబైల్ డేటా"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ఆఫ్లో ఉంది"</string> <string name="bt_is_off" msgid="2640685272289706392">"బ్లూటూత్ ఆఫ్లో ఉంది"</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 3dc4513b906e..ea61018db6c2 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"บลูทูธ"</string> <string name="stream_dtmf" msgid="2447177903892477915">"การส่งสัญญาณเสียงแบบ 2 เสียงพร้อมกัน"</string> <string name="stream_accessibility" msgid="301136219144385106">"การเข้าถึง"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"ทำให้ส่งเสียง"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"สั่น"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"ปิดเสียง"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s แตะเพื่อเปิดเสียง"</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s แตะเพื่อตั้งค่าให้สั่น อาจมีการปิดเสียงบริการการเข้าถึง"</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s แตะเพื่อปิดเสียง อาจมีการปิดเสียงบริการการเข้าถึง"</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Instant App"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Instant Apps ไม่ต้องใช้การติดตั้ง"</string> <string name="app_info" msgid="6856026610594615344">"ข้อมูลแอป"</string> - <string name="go_to_web" msgid="1106022723459948514">"ไปที่เว็บ"</string> + <string name="go_to_web" msgid="2650669128861626071">"ไปที่เบราว์เซอร์"</string> <string name="mobile_data" msgid="7094582042819250762">"ข้อมูลมือถือ"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ปิดอยู่"</string> <string name="bt_is_off" msgid="2640685272289706392">"บลูทูธปิดอยู่"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index f8f915985853..cdf28d6e5348 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Dual multi tone frequency"</string> <string name="stream_accessibility" msgid="301136219144385106">"Pagiging Naa-access"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Ipa-ring"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"I-vibrate"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"I-mute"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. I-tap upang i-unmute."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. I-tap upang itakda na mag-vibrate. Maaaring i-mute ang mga serbisyo sa Accessibility."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. I-tap upang i-mute. Maaaring i-mute ang mga serbisyo sa Accessibility."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Hindi kailangang i-install ang mga instant na app."</string> <string name="app_info" msgid="6856026610594615344">"Impormasyon ng app"</string> - <string name="go_to_web" msgid="1106022723459948514">"Pumunta sa web"</string> + <string name="go_to_web" msgid="2650669128861626071">"Pumunta sa browser"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobile data"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Naka-off ang Wi-Fi"</string> <string name="bt_is_off" msgid="2640685272289706392">"Naka-off ang Bluetooth"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 249964511500..5dc81a1d7eaf 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Çift ton çoklu frekans"</string> <string name="stream_accessibility" msgid="301136219144385106">"Erişilebilirlik"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Zili çaldır"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Titreşim"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Sesi kapat"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Sesi açmak için dokunun."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Titreşime ayarlamak için dokunun. Erişilebilirlik hizmetlerinin sesi kapatılabilir."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Sesi kapatmak için dokunun. Erişilebilirlik hizmetlerinin sesi kapatılabilir."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Hazır Uygulamalar"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Hazır uygulamaların yüklenmesi gerekmez."</string> <string name="app_info" msgid="6856026610594615344">"Uygulama bilgileri"</string> - <string name="go_to_web" msgid="1106022723459948514">"Web\'e git"</string> + <string name="go_to_web" msgid="2650669128861626071">"Tarayıcıya git"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobil veriler"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Kablosuz bağlantı kapalı"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth kapalı"</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 95cd2d078817..8fa1b72239b2 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -498,6 +498,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Двотональний багаточастотний аналоговий сигнал"</string> <string name="stream_accessibility" msgid="301136219144385106">"Спеціальні можливості"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Дзвінок"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Вібросигнал"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Без звуку"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Торкніться, щоб увімкнути звук."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Торкніться, щоб налаштувати вібросигнал. Спеціальні можливості може бути вимкнено."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Торкніться, щоб вимкнути звук. Спеціальні можливості може бути вимкнено."</string> @@ -770,8 +773,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Додатки з миттєвим запуском"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Додатки з миттєвим запуском не потрібно встановлювати."</string> <string name="app_info" msgid="6856026610594615344">"Про додаток"</string> - <!-- no translation found for go_to_web (2650669128861626071) --> - <skip /> + <string name="go_to_web" msgid="2650669128861626071">"Веб-переглядач"</string> <string name="mobile_data" msgid="7094582042819250762">"Мобільний трафік"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi вимкнено"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth вимкнено"</string> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 04bd3401f79f..64980887907f 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -34,17 +34,14 @@ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"اطلاعات"</string> <string name="battery_low_title" msgid="6456385927409742437">"بیٹری کم ہے"</string> <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی ہے"</string> - <!-- no translation found for battery_low_percent_format_saver_started (7879389868952879166) --> - <skip /> + <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی ہے۔ بیٹری سیور آن ہے۔"</string> <string name="invalid_charger" msgid="4549105996740522523">"USB چارجنگ تعاون یافتہ نہیں ہے.\nصرف فراہم کردہ چارجر کا ہی استعمال کریں۔"</string> <string name="invalid_charger_title" msgid="3515740382572798460">"USB چارجنگ تعاون یافتہ نہیں ہے۔"</string> <string name="invalid_charger_text" msgid="5474997287953892710">"صرف فراہم کردہ چارجر استعمال کریں۔"</string> <string name="battery_low_why" msgid="4553600287639198111">"ترتیبات"</string> - <!-- no translation found for battery_saver_confirmation_title (2052100465684817154) --> - <skip /> + <string name="battery_saver_confirmation_title" msgid="2052100465684817154">"بیٹری سیور آن کریں؟"</string> <string name="battery_saver_confirmation_ok" msgid="7507968430447930257">"آن کریں"</string> - <!-- no translation found for battery_saver_start_action (8187820911065797519) --> - <skip /> + <string name="battery_saver_start_action" msgid="8187820911065797519">"بیٹری سیور آن کریں"</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"ترتیبات"</string> <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string> <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"سکرین کو خودکار طور پر گھمائیں"</string> @@ -402,11 +399,9 @@ <string name="user_remove_user_title" msgid="4681256956076895559">"صارف کو ہٹائیں؟"</string> <string name="user_remove_user_message" msgid="1453218013959498039">"اس صارف کی سبھی ایپس اور ڈیٹا حذف کر دیا جائے گا۔"</string> <string name="user_remove_user_remove" msgid="7479275741742178297">"ہٹائیں"</string> - <!-- no translation found for battery_saver_notification_title (8614079794522291840) --> - <skip /> + <string name="battery_saver_notification_title" msgid="8614079794522291840">"بیٹری سیور آن ہے"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"کارکردگی اور پس منظر کا ڈیٹا کم کر دیتا ہے"</string> - <!-- no translation found for battery_saver_notification_action_text (132118784269455533) --> - <skip /> + <string name="battery_saver_notification_action_text" msgid="132118784269455533">"بیٹری سیور آف کریں"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> آپ کی اسکرین پر ڈسپلے ہونے والی ہر چیز کو کیپچر کرنا شروع کر دیگی۔"</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"دوبارہ نہ دکھائیں"</string> <string name="clear_all_notifications_text" msgid="814192889771462828">"سبھی کو صاف کریں"</string> @@ -497,6 +492,12 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"بلوٹوتھ"</string> <string name="stream_dtmf" msgid="2447177903892477915">"دوہری ملٹی ٹون فریکوئنسی"</string> <string name="stream_accessibility" msgid="301136219144385106">"ایکسیسبیلٹی"</string> + <!-- no translation found for volume_ringer_status_normal (4273142424125855384) --> + <skip /> + <!-- no translation found for volume_ringer_status_vibrate (1825615171021346557) --> + <skip /> + <!-- no translation found for volume_ringer_status_silent (6896394161022916369) --> + <skip /> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s۔ آواز چالو کرنے کیلئے تھپتھپائیں۔"</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s۔ ارتعاش پر سیٹ کرنے کیلئے تھپتھپائیں۔ ایکسیسبیلٹی سروسز شاید خاموش ہوں۔"</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s۔ خاموش کرنے کیلئے تھپتھپائیں۔ ایکسیسبیلٹی سروسز شاید خاموش ہوں۔"</string> @@ -761,7 +762,7 @@ <string name="instant_apps" msgid="6647570248119804907">"فوری ایپس"</string> <string name="instant_apps_message" msgid="8116608994995104836">"فوری ایپس کو انسٹالیشن کی ضرورت نہیں ہے۔"</string> <string name="app_info" msgid="6856026610594615344">"ایپ کی معلومات"</string> - <string name="go_to_web" msgid="1106022723459948514">"ویب پر جائیں"</string> + <string name="go_to_web" msgid="2650669128861626071">"براؤزر پر جائیں"</string> <string name="mobile_data" msgid="7094582042819250762">"موبائل ڈیٹا"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi آف ہے"</string> <string name="bt_is_off" msgid="2640685272289706392">"بلوٹوتھ آف ہے"</string> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index e66477fa652f..273079d7dcc2 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Ikkitali ko‘pchastotali ovoz"</string> <string name="stream_accessibility" msgid="301136219144385106">"Maxsus imkoniyatlar"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Jiringlatish"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Tebranish"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Ovozsiz"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Ovozini yoqish uchun ustiga bosing."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tebranishni yoqish uchun ustiga bosing. Maxsus imkoniyatlar ishlamasligi mumkin."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Ovozini o‘chirish uchun ustiga bosing. Maxsus imkoniyatlar ishlamasligi mumkin."</string> @@ -758,7 +761,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Darhol ochiladigan ilovalar"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Darhol ochiladigan ilovalarni o‘rnatish shart emas."</string> <string name="app_info" msgid="6856026610594615344">"Ilova haqida"</string> - <string name="go_to_web" msgid="1106022723459948514">"Brauzerga o‘tish"</string> + <string name="go_to_web" msgid="2650669128861626071">"Brauzerni ochish"</string> <string name="mobile_data" msgid="7094582042819250762">"Mobil internet"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi o‘chiq"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth o‘chiq"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 237920de5146..df062984e2d3 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Tần số đa chuông kép"</string> <string name="stream_accessibility" msgid="301136219144385106">"Trợ năng"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Đổ chuông"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Rung"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Tắt tiếng"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Nhấn để bật tiếng."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Nhấn để đặt chế độ rung. Bạn có thể tắt tiếng dịch vụ trợ năng."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Nhấn để tắt tiếng. Bạn có thể tắt tiếng dịch vụ trợ năng."</string> @@ -758,7 +761,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Ứng dụng tức thì"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Ứng dụng tức thì không yêu cầu cài đặt."</string> <string name="app_info" msgid="6856026610594615344">"Thông tin ứng dụng"</string> - <string name="go_to_web" msgid="1106022723459948514">"Truy cập web"</string> + <string name="go_to_web" msgid="2650669128861626071">"Đi tới trình duyệt"</string> <string name="mobile_data" msgid="7094582042819250762">"Dữ liệu di động"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi tắt"</string> <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth tắt"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index d80d1bf7d1e5..f7999a6d9789 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"蓝牙"</string> <string name="stream_dtmf" msgid="2447177903892477915">"双音多频"</string> <string name="stream_accessibility" msgid="301136219144385106">"无障碍"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"响铃"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"振动"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"静音"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s。点按即可取消静音。"</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s。点按即可设为振动,但可能会同时将无障碍服务设为静音。"</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s。点按即可设为静音,但可能会同时将无障碍服务设为静音。"</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"免安装应用"</string> <string name="instant_apps_message" msgid="8116608994995104836">"免安装应用无需安装就能使用。"</string> <string name="app_info" msgid="6856026610594615344">"应用信息"</string> - <string name="go_to_web" msgid="1106022723459948514">"转到网页版"</string> + <string name="go_to_web" msgid="2650669128861626071">"转到浏览器"</string> <string name="mobile_data" msgid="7094582042819250762">"移动数据"</string> <string name="wifi_is_off" msgid="1838559392210456893">"WLAN 已关闭"</string> <string name="bt_is_off" msgid="2640685272289706392">"蓝牙已关闭"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 7da008d46704..188ad7cae870 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -494,6 +494,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"藍牙"</string> <string name="stream_dtmf" msgid="2447177903892477915">"雙音多頻訊號"</string> <string name="stream_accessibility" msgid="301136219144385106">"無障礙功能"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"鈴聲"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"震動"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"靜音"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s。輕按即可取消靜音。"</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s。輕按即可設為震動。無障礙功能服務可能已經設為靜音。"</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s。輕按即可設為靜音。無障礙功能服務可能已經設為靜音。"</string> @@ -758,7 +761,7 @@ <string name="instant_apps" msgid="6647570248119804907">"即時應用程式"</string> <string name="instant_apps_message" msgid="8116608994995104836">"即時應用程式無需安裝即可使用。"</string> <string name="app_info" msgid="6856026610594615344">"應用程式資料"</string> - <string name="go_to_web" msgid="1106022723459948514">"前往網頁版"</string> + <string name="go_to_web" msgid="2650669128861626071">"前往瀏覽器"</string> <string name="mobile_data" msgid="7094582042819250762">"流動數據"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi 已關閉"</string> <string name="bt_is_off" msgid="2640685272289706392">"藍牙已關閉"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index efb48cda55e2..75f8015fda5a 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"藍牙"</string> <string name="stream_dtmf" msgid="2447177903892477915">"雙音多頻"</string> <string name="stream_accessibility" msgid="301136219144385106">"協助工具"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"鈴聲"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"震動"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"靜音"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s。輕觸即可取消靜音。"</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s。輕觸即可設為震動,但系統可能會將無障礙服務一併設為靜音。"</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s。輕觸即可設為靜音,但系統可能會將無障礙服務一併設為靜音。"</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"免安裝應用程式"</string> <string name="instant_apps_message" msgid="8116608994995104836">"免安裝應用程式不必安裝就能使用。"</string> <string name="app_info" msgid="6856026610594615344">"應用程式資訊"</string> - <string name="go_to_web" msgid="1106022723459948514">"前往網頁版"</string> + <string name="go_to_web" msgid="2650669128861626071">"前往瀏覽器"</string> <string name="mobile_data" msgid="7094582042819250762">"行動數據"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi 已關閉"</string> <string name="bt_is_off" msgid="2640685272289706392">"藍牙已關閉"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 5094de9962a4..b3b26dcded84 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -492,6 +492,9 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"I-Bluetooth"</string> <string name="stream_dtmf" msgid="2447177903892477915">"Ifrikhwensi yethoni engakuningi"</string> <string name="stream_accessibility" msgid="301136219144385106">"Ukufinyeleleka"</string> + <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Khalisa"</string> + <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Dlidlizela"</string> + <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Thulisa"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Thepha ukuze ususe ukuthula."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Thepha ukuze usethe ukudlidliza. Amasevisi okufinyelela angathuliswa."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Thepha ukuze uthulise. Amasevisi okufinyelela angathuliswa."</string> @@ -756,7 +759,7 @@ <string name="instant_apps" msgid="6647570248119804907">"Izinhlelo zokusebenza ezisheshayo"</string> <string name="instant_apps_message" msgid="8116608994995104836">"Izinhlelo zokusebenza ezisheshayo azidingi ukufakwa."</string> <string name="app_info" msgid="6856026610594615344">"Ulwazi lohlelo lokusebenza"</string> - <string name="go_to_web" msgid="1106022723459948514">"Iya kuwebhu"</string> + <string name="go_to_web" msgid="2650669128861626071">"Iya kusiphequluli"</string> <string name="mobile_data" msgid="7094582042819250762">"Idatha yeselula"</string> <string name="wifi_is_off" msgid="1838559392210456893">"I-Wi-Fi ivaliwe"</string> <string name="bt_is_off" msgid="2640685272289706392">"I-Bluetooth ivaliwe"</string> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 41b007af46ae..d58b69deb2df 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -347,6 +347,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray(); private static int sCurrentUser; + private Runnable mUpdateFingerprintListeningState = this::updateFingerprintListeningState; public synchronized static void setCurrentUser(int currentUser) { sCurrentUser = currentUser; @@ -1666,7 +1667,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { public void setSwitchingUser(boolean switching) { mSwitchingUser = switching; - updateFingerprintListeningState(); + // Since this comes in on a binder thread, we need to post if first + mHandler.post(mUpdateFingerprintListeningState); } private void sendUpdates(KeyguardUpdateMonitorCallback callback) { diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index 45b11aac5f35..ebeb35189008 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -26,9 +26,11 @@ import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.Dependency.DependencyProvider; import com.android.systemui.keyguard.DismissCallbackRegistry; +import com.android.systemui.qs.QSTileHost; import com.android.systemui.statusbar.KeyguardIndicationController; import com.android.systemui.statusbar.NotificationGutsManager; import com.android.systemui.statusbar.NotificationLockscreenUserManager; +import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.ScrimView; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBouncer; @@ -36,9 +38,8 @@ import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.statusbar.phone.LockIcon; import com.android.systemui.statusbar.phone.LockscreenWallpaper; import com.android.systemui.statusbar.phone.NotificationIconAreaController; -import com.android.systemui.statusbar.phone.StatusBar; -import com.android.systemui.qs.QSTileHost; import com.android.systemui.statusbar.phone.ScrimController; +import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; @@ -115,5 +116,8 @@ public class SystemUIFactory { () -> new NotificationLockscreenUserManager(context)); providers.put(NotificationGutsManager.class, () -> new NotificationGutsManager( Dependency.get(NotificationLockscreenUserManager.class), context)); + providers.put(NotificationRemoteInputManager.class, + () -> new NotificationRemoteInputManager( + Dependency.get(NotificationLockscreenUserManager.class), context)); } } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java index 6f8bcff16a83..a409fcb4504a 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java @@ -63,7 +63,7 @@ public class DozeFactory { new DozeFalsingManagerAdapter(FalsingManager.getInstance(context)), createDozeTriggers(context, sensorManager, host, alarmManager, config, params, handler, wakeLock, machine), - createDozeUi(context, host, wakeLock, machine, handler, alarmManager), + createDozeUi(context, host, wakeLock, machine, handler, alarmManager, params), new DozeScreenState(wrappedService, handler), createDozeScreenBrightness(context, wrappedService, sensorManager, host, handler), }); @@ -89,8 +89,9 @@ public class DozeFactory { } private DozeMachine.Part createDozeUi(Context context, DozeHost host, WakeLock wakeLock, - DozeMachine machine, Handler handler, AlarmManager alarmManager) { - return new DozeUi(context, alarmManager, machine, wakeLock, host, handler); + DozeMachine machine, Handler handler, AlarmManager alarmManager, + DozeParameters params) { + return new DozeUi(context, alarmManager, machine, wakeLock, host, handler, params); } public static DozeHost getHost(DozeService service) { diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java index 2f607eee4f16..6a29299872a4 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java @@ -38,6 +38,7 @@ public interface DozeHost { void extendPulse(); void setAnimateWakeup(boolean animateWakeup); + void setAnimateScreenOff(boolean animateScreenOff); void onDoubleTap(float x, float y); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java index 851b78cfcd49..b352ec97b209 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java @@ -23,6 +23,7 @@ import android.os.SystemClock; import android.text.format.Formatter; import android.util.Log; +import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.util.AlarmTimeout; import com.android.systemui.util.wakelock.WakeLock; @@ -41,18 +42,22 @@ public class DozeUi implements DozeMachine.Part { private final WakeLock mWakeLock; private final DozeMachine mMachine; private final AlarmTimeout mTimeTicker; + private final boolean mCanAnimateWakeup; private long mLastTimeTickElapsed = 0; public DozeUi(Context context, AlarmManager alarmManager, DozeMachine machine, - WakeLock wakeLock, DozeHost host, Handler handler) { + WakeLock wakeLock, DozeHost host, Handler handler, + DozeParameters params) { mContext = context; mMachine = machine; mWakeLock = wakeLock; mHost = host; mHandler = handler; + mCanAnimateWakeup = !params.getDisplayNeedsBlanking(); mTimeTicker = new AlarmTimeout(alarmManager, this::onTimeTick, "doze_time_tick", handler); + mHost.setAnimateScreenOff(params.getCanControlScreenOffAnimation()); } private void pulseWhileDozing(int reason) { @@ -106,7 +111,7 @@ public class DozeUi implements DozeMachine.Part { // Keep current state. break; default: - mHost.setAnimateWakeup(false); + mHost.setAnimateWakeup(mCanAnimateWakeup); break; } } diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index 3b54e11447b7..5c8c3f356fae 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -333,7 +333,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, } else if (GLOBAL_ACTION_KEY_RESTART.equals(actionKey)) { mItems.add(new RestartAction()); } else if (GLOBAL_ACTION_KEY_LOGOUT.equals(actionKey)) { - if (mDevicePolicyManager.isLogoutButtonEnabled() + if (mDevicePolicyManager.isLogoutEnabled() && getCurrentUser().id != UserHandle.USER_SYSTEM) { mItems.add(new LogoutAction()); mHasLogoutButton = true; diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 1faf981f8a83..8fa66e0fa496 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -164,7 +164,6 @@ public class KeyguardViewMediator extends SystemUI { private static final int NOTIFY_SCREEN_TURNED_ON = 15; private static final int NOTIFY_SCREEN_TURNED_OFF = 16; private static final int NOTIFY_STARTED_GOING_TO_SLEEP = 17; - private static final int SET_SWITCHING_USER = 18; /** * The default amount of time we stay awake (used for all key input) @@ -1419,11 +1418,7 @@ public class KeyguardViewMediator extends SystemUI { } public void setSwitchingUser(boolean switching) { - Trace.beginSection("KeyguardViewMediator#setSwitchingUser"); - mHandler.removeMessages(SET_SWITCHING_USER); - Message msg = mHandler.obtainMessage(SET_SWITCHING_USER, switching ? 1 : 0, 0); - mHandler.sendMessage(msg); - Trace.endSection(); + KeyguardUpdateMonitor.getInstance(mContext).setSwitchingUser(switching); } /** @@ -1563,11 +1558,6 @@ public class KeyguardViewMediator extends SystemUI { Log.w(TAG, "Timeout while waiting for activity drawn!"); Trace.endSection(); break; - case SET_SWITCHING_USER: - Trace.beginSection("KeyguardViewMediator#handleMessage SET_SWITCHING_USER"); - KeyguardUpdateMonitor.getInstance(mContext).setSwitchingUser(msg.arg1 != 0); - Trace.endSection(); - break; } } }; diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java index 5fcd0061fa6f..6db46b5917b6 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java @@ -38,7 +38,6 @@ import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.graphics.Bitmap; -import android.graphics.Canvas; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; import android.graphics.Matrix; @@ -58,10 +57,13 @@ import android.provider.MediaStore; import android.util.DisplayMetrics; import android.util.Slog; import android.view.Display; +import android.view.DisplayListCanvas; import android.view.LayoutInflater; import android.view.MotionEvent; +import android.view.RenderNode; import android.view.Surface; import android.view.SurfaceControl; +import android.view.ThreadedRenderer; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; @@ -153,7 +155,6 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { int previewWidth = data.previewWidth; int previewHeight = data.previewheight; - Canvas c = new Canvas(); Paint paint = new Paint(); ColorMatrix desat = new ColorMatrix(); desat.setSaturation(0.25f); @@ -161,23 +162,17 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { Matrix matrix = new Matrix(); int overlayColor = 0x40FFFFFF; - Bitmap picture = Bitmap.createBitmap(previewWidth, previewHeight, Bitmap.Config.ARGB_8888); matrix.setTranslate((previewWidth - mImageWidth) / 2, (previewHeight - mImageHeight) / 2); - c.setBitmap(picture); - c.drawBitmap(data.image, matrix, paint); - c.drawColor(overlayColor); - c.setBitmap(null); + Bitmap picture = generateAdjustedHwBitmap(data.image, previewWidth, previewHeight, matrix, + paint, overlayColor); // Note, we can't use the preview for the small icon, since it is non-square float scale = (float) iconSize / Math.min(mImageWidth, mImageHeight); - Bitmap icon = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888); matrix.setScale(scale, scale); matrix.postTranslate((iconSize - (scale * mImageWidth)) / 2, (iconSize - (scale * mImageHeight)) / 2); - c.setBitmap(icon); - c.drawBitmap(data.image, matrix, paint); - c.drawColor(overlayColor); - c.setBitmap(null); + Bitmap icon = generateAdjustedHwBitmap(data.image, iconSize, iconSize, matrix, paint, + overlayColor); // Show the intermediate notification mTickerAddSpace = !mTickerAddSpace; @@ -231,6 +226,22 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { mNotificationStyle.bigLargeIcon((Bitmap) null); } + /** + * Generates a new hardware bitmap with specified values, copying the content from the passed + * in bitmap. + */ + private Bitmap generateAdjustedHwBitmap(Bitmap bitmap, int width, int height, Matrix matrix, + Paint paint, int color) { + RenderNode node = RenderNode.create("ScreenshotCanvas", null); + node.setLeftTopRightBottom(0, 0, width, height); + node.setClipToBounds(false); + DisplayListCanvas canvas = node.start(width, height); + canvas.drawColor(color); + canvas.drawBitmap(bitmap, matrix, paint); + node.end(canvas); + return ThreadedRenderer.createHardwareBitmap(node, width, height); + } + @Override protected Void doInBackground(Void... params) { if (isCancelled()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index e04bd0e72929..f53eb4897ad5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -206,7 +206,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private OnClickListener mExpandClickListener = new OnClickListener() { @Override public void onClick(View v) { - if (!mShowingPublic && (!mIsLowPriority || isExpanded()) + if (!shouldShowPublic() && (!mIsLowPriority || isExpanded()) && mGroupManager.isSummaryOfGroup(mStatusBarNotification)) { mGroupExpansionChanging = true; final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification); @@ -790,7 +790,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView * {@link #getNotificationHeader()} in case it is a low-priority group. */ public NotificationHeaderView getVisibleNotificationHeader() { - if (mIsSummaryWithChildren && !mShowingPublic) { + if (mIsSummaryWithChildren && !shouldShowPublic()) { return mChildrenContainer.getVisibleHeader(); } return getShowingLayout().getVisibleNotificationHeader(); @@ -1512,10 +1512,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } private void updateChildrenVisibility() { - mPrivateLayout.setVisibility(!mShowingPublic && !mIsSummaryWithChildren ? VISIBLE + mPrivateLayout.setVisibility(!shouldShowPublic() && !mIsSummaryWithChildren ? VISIBLE : INVISIBLE); if (mChildrenContainer != null) { - mChildrenContainer.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE + mChildrenContainer.setVisibility(!shouldShowPublic() && mIsSummaryWithChildren ? VISIBLE : INVISIBLE); } // The limits might have changed if the view suddenly became a group or vice versa @@ -1566,7 +1566,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } public boolean isExpandable() { - if (mIsSummaryWithChildren && !mShowingPublic) { + if (mIsSummaryWithChildren && !shouldShowPublic()) { return !mChildrenExpanded; } return mEnableNonGroupedNotificationExpand && mExpandable; @@ -1611,7 +1611,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView */ public void setUserExpanded(boolean userExpanded, boolean allowChildExpansion) { mFalsingManager.setNotificationExpanded(); - if (mIsSummaryWithChildren && !mShowingPublic && allowChildExpansion + if (mIsSummaryWithChildren && !shouldShowPublic() && allowChildExpansion && !mChildrenContainer.showingAsLowPriority()) { final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification); mGroupManager.setGroupExpanded(mStatusBarNotification, userExpanded); @@ -1906,7 +1906,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE); updateChildrenVisibility(); } else { - animateShowingPublic(delay, duration); + animateShowingPublic(delay, duration, mShowingPublic); } NotificationContentView showingLayout = getShowingLayout(); showingLayout.updateBackgroundColor(animated); @@ -1916,13 +1916,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mShowingPublicInitialized = true; } - private void animateShowingPublic(long delay, long duration) { + private void animateShowingPublic(long delay, long duration, boolean showingPublic) { View[] privateViews = mIsSummaryWithChildren ? new View[] {mChildrenContainer} : new View[] {mPrivateLayout}; View[] publicViews = new View[] {mPublicLayout}; - View[] hiddenChildren = mShowingPublic ? privateViews : publicViews; - View[] shownChildren = mShowingPublic ? publicViews : privateViews; + View[] hiddenChildren = showingPublic ? privateViews : publicViews; + View[] shownChildren = showingPublic ? publicViews : privateViews; for (final View hiddenView : hiddenChildren) { hiddenView.setVisibility(View.VISIBLE); hiddenView.animate().cancel(); @@ -1959,7 +1959,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView * see {@link #isClearable()}. */ public boolean canViewBeDismissed() { - return isClearable() && (!mShowingPublic || !mSensitiveHiddenInGeneral); + return isClearable() && (!shouldShowPublic() || !mSensitiveHiddenInGeneral); + } + + private boolean shouldShowPublic() { + return mSensitive && mHideSensitiveForIntrinsicHeight; } public void makeActionsVisibile() { @@ -2005,7 +2009,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView @Override public boolean isContentExpandable() { - if (mIsSummaryWithChildren && !mShowingPublic) { + if (mIsSummaryWithChildren && !shouldShowPublic()) { return true; } NotificationContentView showingLayout = getShowingLayout(); @@ -2014,7 +2018,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView @Override protected View getContentView() { - if (mIsSummaryWithChildren && !mShowingPublic) { + if (mIsSummaryWithChildren && !shouldShowPublic()) { return mChildrenContainer; } return getShowingLayout(); @@ -2079,7 +2083,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView @Override public int getMaxContentHeight() { - if (mIsSummaryWithChildren && !mShowingPublic) { + if (mIsSummaryWithChildren && !shouldShowPublic()) { return mChildrenContainer.getMaxContentHeight(); } NotificationContentView showingLayout = getShowingLayout(); @@ -2093,7 +2097,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } else if (!ignoreTemporaryStates && isHeadsUpAllowed() && mIsHeadsUp && mHeadsUpManager.isTrackingHeadsUp()) { return getPinnedHeadsUpHeight(false /* atLeastMinHeight */); - } else if (mIsSummaryWithChildren && !isGroupExpanded() && !mShowingPublic) { + } else if (mIsSummaryWithChildren && !isGroupExpanded() && !shouldShowPublic()) { return mChildrenContainer.getMinHeight(); } else if (!ignoreTemporaryStates && isHeadsUpAllowed() && mIsHeadsUp) { return mHeadsUpHeight; @@ -2104,7 +2108,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView @Override public int getCollapsedHeight() { - if (mIsSummaryWithChildren && !mShowingPublic) { + if (mIsSummaryWithChildren && !shouldShowPublic()) { return mChildrenContainer.getCollapsedHeight(); } return getMinHeight(); @@ -2144,7 +2148,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } public NotificationContentView getShowingLayout() { - return mShowingPublic ? mPublicLayout : mPrivateLayout; + return shouldShowPublic() ? mPublicLayout : mPrivateLayout; } public void setLegacy(boolean legacy) { @@ -2250,7 +2254,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView if (header != null && header.isInTouchRect(x - getTranslation(), y)) { return true; } - if ((!mIsSummaryWithChildren || mShowingPublic) + if ((!mIsSummaryWithChildren || shouldShowPublic()) && getShowingLayout().disallowSingleClick(x, y)) { return true; } @@ -2280,7 +2284,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView if (canViewBeDismissed()) { info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_DISMISS); } - boolean expandable = mShowingPublic; + boolean expandable = shouldShowPublic(); boolean isExpanded = false; if (!expandable) { if (mIsSummaryWithChildren) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java index 6bcd174adeae..4952da4b1fec 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java @@ -37,10 +37,13 @@ public class NotificationListener extends NotificationListenerWithPlugins { private static final String TAG = "NotificationListener"; private final NotificationPresenter mPresenter; + private final NotificationRemoteInputManager mRemoteInputManager; private final Context mContext; - public NotificationListener(NotificationPresenter presenter, Context context) { + public NotificationListener(NotificationPresenter presenter, + NotificationRemoteInputManager remoteInputManager, Context context) { mPresenter = presenter; + mRemoteInputManager = remoteInputManager; mContext = context; } @@ -69,7 +72,7 @@ public class NotificationListener extends NotificationListenerWithPlugins { mPresenter.getHandler().post(() -> { processForRemoteInput(sbn.getNotification(), mContext); String key = sbn.getKey(); - mPresenter.getKeysKeptForRemoteInput().remove(key); + mRemoteInputManager.getKeysKeptForRemoteInput().remove(key); boolean isUpdate = mPresenter.getNotificationData().get(key) != null; // In case we don't allow child notifications, we ignore children of // notifications that have a summary, since` we're not going to show them diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java index 4eca2415d5c3..33c72534b1b6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar; import android.content.Intent; import android.os.Handler; import android.service.notification.NotificationListenerService; +import android.view.View; import java.util.Set; @@ -29,7 +30,7 @@ import java.util.Set; * want to perform some action before doing so). */ public interface NotificationPresenter extends NotificationUpdateHandler, - NotificationData.Environment { + NotificationData.Environment, NotificationRemoteInputManager.Callback { /** * Returns true if the presenter is not visible. For example, it may not be necessary to do @@ -81,14 +82,6 @@ public interface NotificationPresenter extends NotificationUpdateHandler, void onWorkChallengeChanged(); /** - * Notifications in this set are kept around when they were canceled in response to a remote - * input interaction. This allows us to show what you replied and allows you to continue typing - * into it. - */ - // TODO: Create NotificationEntryManager and move this method to there. - Set<String> getKeysKeptForRemoteInput(); - - /** * Called when the current user changes. * @param newUserId new user id */ @@ -98,4 +91,20 @@ public interface NotificationPresenter extends NotificationUpdateHandler, * Gets the NotificationLockscreenUserManager for this Presenter. */ NotificationLockscreenUserManager getNotificationLockscreenUserManager(); + + /** + * Wakes the device up if dozing. + * + * @param time the time when the request to wake up was issued + * @param where which view caused this wake up request + */ + void wakeUpIfDozing(long time, View where); + + /** + * True if the device currently requires a PIN, pattern, or password to unlock. + * + * @param userId user id to query about + * @return true iff the device is locked + */ + boolean isDeviceLocked(int userId); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java new file mode 100644 index 000000000000..7827f62970e7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java @@ -0,0 +1,441 @@ +/* + * 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.systemui.statusbar; + +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY; + +import android.app.ActivityManager; +import android.app.PendingIntent; +import android.app.RemoteInput; +import android.content.Context; +import android.content.Intent; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemClock; +import android.os.SystemProperties; +import android.os.UserManager; +import android.service.notification.StatusBarNotification; +import android.util.ArraySet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.widget.RemoteViews; +import android.widget.TextView; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.statusbar.IStatusBarService; +import com.android.systemui.Dumpable; +import com.android.systemui.statusbar.policy.RemoteInputView; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.Set; + +/** + * Class for handling remote input state over a set of notifications. This class handles things + * like keeping notifications temporarily that were cancelled as a response to a remote input + * interaction, keeping track of notifications to remove when NotificationPresenter is collapsed, + * and handling clicks on remote views. + */ +public class NotificationRemoteInputManager implements Dumpable { + public static final boolean ENABLE_REMOTE_INPUT = + SystemProperties.getBoolean("debug.enable_remote_input", true); + public static final boolean FORCE_REMOTE_INPUT_HISTORY = + SystemProperties.getBoolean("debug.force_remoteinput_history", true); + private static final boolean DEBUG = false; + private static final String TAG = "NotificationRemoteInputManager"; + + /** + * How long to wait before auto-dismissing a notification that was kept for remote input, and + * has now sent a remote input. We auto-dismiss, because the app may not see a reason to cancel + * these given that they technically don't exist anymore. We wait a bit in case the app issues + * an update. + */ + private static final int REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY = 200; + + protected final ArraySet<NotificationData.Entry> mRemoteInputEntriesToRemoveOnCollapse = + new ArraySet<>(); + protected final NotificationLockscreenUserManager mLockscreenUserManager; + + /** + * Notifications with keys in this set are not actually around anymore. We kept them around + * when they were canceled in response to a remote input interaction. This allows us to show + * what you replied and allows you to continue typing into it. + */ + protected final ArraySet<String> mKeysKeptForRemoteInput = new ArraySet<>(); + protected final Context mContext; + private final UserManager mUserManager; + + protected RemoteInputController mRemoteInputController; + protected NotificationPresenter mPresenter; + protected IStatusBarService mBarService; + protected Callback mCallback; + + private final RemoteViews.OnClickHandler mOnClickHandler = new RemoteViews.OnClickHandler() { + + @Override + public boolean onClickHandler( + final View view, final PendingIntent pendingIntent, final Intent fillInIntent) { + mPresenter.wakeUpIfDozing(SystemClock.uptimeMillis(), view); + + if (handleRemoteInput(view, pendingIntent)) { + return true; + } + + if (DEBUG) { + Log.v(TAG, "Notification click handler invoked for intent: " + pendingIntent); + } + logActionClick(view); + // The intent we are sending is for the application, which + // won't have permission to immediately start an activity after + // the user switches to home. We know it is safe to do at this + // point, so make sure new activity switches are now allowed. + try { + ActivityManager.getService().resumeAppSwitches(); + } catch (RemoteException e) { + } + return mCallback.handleRemoteViewClick(view, pendingIntent, fillInIntent, + () -> superOnClickHandler(view, pendingIntent, fillInIntent)); + } + + private void logActionClick(View view) { + ViewParent parent = view.getParent(); + String key = getNotificationKeyForParent(parent); + if (key == null) { + Log.w(TAG, "Couldn't determine notification for click."); + return; + } + int index = -1; + // If this is a default template, determine the index of the button. + if (view.getId() == com.android.internal.R.id.action0 && + parent != null && parent instanceof ViewGroup) { + ViewGroup actionGroup = (ViewGroup) parent; + index = actionGroup.indexOfChild(view); + } + try { + mBarService.onNotificationActionClick(key, index); + } catch (RemoteException e) { + // Ignore + } + } + + private String getNotificationKeyForParent(ViewParent parent) { + while (parent != null) { + if (parent instanceof ExpandableNotificationRow) { + return ((ExpandableNotificationRow) parent) + .getStatusBarNotification().getKey(); + } + parent = parent.getParent(); + } + return null; + } + + private boolean superOnClickHandler(View view, PendingIntent pendingIntent, + Intent fillInIntent) { + return super.onClickHandler(view, pendingIntent, fillInIntent, + WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY); + } + + private boolean handleRemoteInput(View view, PendingIntent pendingIntent) { + if (mCallback.shouldHandleRemoteInput(view, pendingIntent)) { + return true; + } + + Object tag = view.getTag(com.android.internal.R.id.remote_input_tag); + RemoteInput[] inputs = null; + if (tag instanceof RemoteInput[]) { + inputs = (RemoteInput[]) tag; + } + + if (inputs == null) { + return false; + } + + RemoteInput input = null; + + for (RemoteInput i : inputs) { + if (i.getAllowFreeFormInput()) { + input = i; + } + } + + if (input == null) { + return false; + } + + ViewParent p = view.getParent(); + RemoteInputView riv = null; + while (p != null) { + if (p instanceof View) { + View pv = (View) p; + if (pv.isRootNamespace()) { + riv = findRemoteInputView(pv); + break; + } + } + p = p.getParent(); + } + ExpandableNotificationRow row = null; + while (p != null) { + if (p instanceof ExpandableNotificationRow) { + row = (ExpandableNotificationRow) p; + break; + } + p = p.getParent(); + } + + if (row == null) { + return false; + } + + row.setUserExpanded(true); + + if (!mLockscreenUserManager.shouldAllowLockscreenRemoteInput()) { + final int userId = pendingIntent.getCreatorUserHandle().getIdentifier(); + if (mLockscreenUserManager.isLockscreenPublicMode(userId)) { + mCallback.onLockedRemoteInput(row, view); + return true; + } + if (mUserManager.getUserInfo(userId).isManagedProfile() + && mPresenter.isDeviceLocked(userId)) { + mCallback.onLockedWorkRemoteInput(userId, row, view); + return true; + } + } + + if (riv == null) { + riv = findRemoteInputView(row.getPrivateLayout().getExpandedChild()); + if (riv == null) { + return false; + } + if (!row.getPrivateLayout().getExpandedChild().isShown()) { + mCallback.onMakeExpandedVisibleForRemoteInput(row, view); + return true; + } + } + + int width = view.getWidth(); + if (view instanceof TextView) { + // Center the reveal on the text which might be off-center from the TextView + TextView tv = (TextView) view; + if (tv.getLayout() != null) { + int innerWidth = (int) tv.getLayout().getLineWidth(0); + innerWidth += tv.getCompoundPaddingLeft() + tv.getCompoundPaddingRight(); + width = Math.min(width, innerWidth); + } + } + int cx = view.getLeft() + width / 2; + int cy = view.getTop() + view.getHeight() / 2; + int w = riv.getWidth(); + int h = riv.getHeight(); + int r = Math.max( + Math.max(cx + cy, cx + (h - cy)), + Math.max((w - cx) + cy, (w - cx) + (h - cy))); + + riv.setRevealParameters(cx, cy, r); + riv.setPendingIntent(pendingIntent); + riv.setRemoteInput(inputs, input); + riv.focusAnimated(); + + return true; + } + + private RemoteInputView findRemoteInputView(View v) { + if (v == null) { + return null; + } + return (RemoteInputView) v.findViewWithTag(RemoteInputView.VIEW_TAG); + } + }; + + public NotificationRemoteInputManager(NotificationLockscreenUserManager lockscreenUserManager, + Context context) { + mLockscreenUserManager = lockscreenUserManager; + mContext = context; + mBarService = IStatusBarService.Stub.asInterface( + ServiceManager.getService(Context.STATUS_BAR_SERVICE)); + mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + } + + public void setUpWithPresenter(NotificationPresenter presenter, + Callback callback, + RemoteInputController.Delegate delegate) { + mPresenter = presenter; + mCallback = callback; + mRemoteInputController = new RemoteInputController(delegate); + mRemoteInputController.addCallback(new RemoteInputController.Callback() { + @Override + public void onRemoteInputSent(NotificationData.Entry entry) { + if (FORCE_REMOTE_INPUT_HISTORY && mKeysKeptForRemoteInput.contains(entry.key)) { + mPresenter.removeNotification(entry.key, null); + } else if (mRemoteInputEntriesToRemoveOnCollapse.contains(entry)) { + // We're currently holding onto this notification, but from the apps point of + // view it is already canceled, so we'll need to cancel it on the apps behalf + // after sending - unless the app posts an update in the mean time, so wait a + // bit. + mPresenter.getHandler().postDelayed(() -> { + if (mRemoteInputEntriesToRemoveOnCollapse.remove(entry)) { + mPresenter.removeNotification(entry.key, null); + } + }, REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY); + } + } + }); + + } + + public RemoteInputController getController() { + return mRemoteInputController; + } + + public void onUpdateNotification(NotificationData.Entry entry) { + mRemoteInputEntriesToRemoveOnCollapse.remove(entry); + } + + /** + * Returns true if NotificationRemoteInputManager wants to keep this notification around. + * + * @param entry notification being removed + */ + public boolean onRemoveNotification(NotificationData.Entry entry) { + if (entry != null && mRemoteInputController.isRemoteInputActive(entry) + && (entry.row != null && !entry.row.isDismissed())) { + mRemoteInputEntriesToRemoveOnCollapse.add(entry); + return true; + } + return false; + } + + public void onPerformRemoveNotification(StatusBarNotification n, + NotificationData.Entry entry) { + if (mRemoteInputController.isRemoteInputActive(entry)) { + mRemoteInputController.removeRemoteInput(entry, null); + } + if (FORCE_REMOTE_INPUT_HISTORY + && mKeysKeptForRemoteInput.contains(n.getKey())) { + mKeysKeptForRemoteInput.remove(n.getKey()); + } + } + + public void removeRemoteInputEntriesKeptUntilCollapsed() { + for (int i = 0; i < mRemoteInputEntriesToRemoveOnCollapse.size(); i++) { + NotificationData.Entry entry = mRemoteInputEntriesToRemoveOnCollapse.valueAt(i); + mRemoteInputController.removeRemoteInput(entry, null); + mPresenter.removeNotification(entry.key, mPresenter.getLatestRankingMap()); + } + mRemoteInputEntriesToRemoveOnCollapse.clear(); + } + + public void checkRemoteInputOutside(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar + && event.getX() == 0 && event.getY() == 0 // a touch outside both bars + && mRemoteInputController.isRemoteInputActive()) { + mRemoteInputController.closeRemoteInputs(); + } + } + + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("NotificationRemoteInputManager state:"); + pw.print(" mRemoteInputEntriesToRemoveOnCollapse: "); + pw.println(mRemoteInputEntriesToRemoveOnCollapse); + pw.print(" mKeysKeptForRemoteInput: "); + pw.println(mKeysKeptForRemoteInput); + } + + public void bindRow(ExpandableNotificationRow row) { + row.setRemoteInputController(mRemoteInputController); + row.setRemoteViewClickHandler(mOnClickHandler); + } + + public Set<String> getKeysKeptForRemoteInput() { + return mKeysKeptForRemoteInput; + } + + @VisibleForTesting + public Set<NotificationData.Entry> getRemoteInputEntriesToRemoveOnCollapse() { + return mRemoteInputEntriesToRemoveOnCollapse; + } + + /** + * Callback for various remote input related events, or for providing information that + * NotificationRemoteInputManager needs to know to decide what to do. + */ + public interface Callback { + + /** + * Called when remote input was activated but the device is locked. + * + * @param row + * @param clicked + */ + void onLockedRemoteInput(ExpandableNotificationRow row, View clicked); + + /** + * Called when remote input was activated but the device is locked and in a managed profile. + * + * @param userId + * @param row + * @param clicked + */ + void onLockedWorkRemoteInput(int userId, ExpandableNotificationRow row, View clicked); + + /** + * Called when a row should be made expanded for the purposes of remote input. + * + * @param row + * @param clickedView + */ + void onMakeExpandedVisibleForRemoteInput(ExpandableNotificationRow row, View clickedView); + + /** + * Return whether or not remote input should be handled for this view. + * + * @param view + * @param pendingIntent + * @return true iff the remote input should be handled + */ + boolean shouldHandleRemoteInput(View view, PendingIntent pendingIntent); + + /** + * Performs any special handling for a remote view click. The default behaviour can be + * called through the defaultHandler parameter. + * + * @param view + * @param pendingIntent + * @param fillInIntent + * @param defaultHandler + * @return true iff the click was handled + */ + boolean handleRemoteViewClick(View view, PendingIntent pendingIntent, Intent fillInIntent, + ClickHandler defaultHandler); + } + + /** + * Helper interface meant for passing the default on click behaviour to NotificationPresenter, + * so it may do its own handling before invoking the default behaviour. + */ + public interface ClickHandler { + /** + * Tries to handle a click on a remote view. + * + * @return true iff the click was handled + */ + boolean handleClick(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java index 3f57c2f9384f..50cbd69e31c8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java @@ -119,6 +119,28 @@ public class DozeParameters { return mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT); } + /** + * Some screens need to be completely black before changing the display power mode, + * unexpected behavior might happen if this parameter isn't respected. + * + * @return true if screen needs to be completely black before a power transition. + */ + public boolean getDisplayNeedsBlanking() { + return mContext.getResources().getBoolean( + com.android.internal.R.bool.config_displayBlanksAfterDoze); + } + + /** + * Whether we can implement our own screen off animation or if we need + * to rely on DisplayPowerManager to dim the display. + * + * @return true if SystemUI can control the screen off animation. + */ + public boolean getCanControlScreenOffAnimation() { + return !mContext.getResources().getBoolean( + com.android.internal.R.bool.config_dozeAfterScreenOff); + } + private boolean getBoolean(String propName, int resId) { return SystemProperties.getBoolean(propName, mContext.getResources().getBoolean(resId)); } 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 05fcbb0a11b6..168758f64b60 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -195,6 +195,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, public void transitionTo(ScrimState state, Callback callback) { if (state == mState) { + // Call the callback anyway, unless it's already enqueued + if (callback != null && mCallback != callback) { + callback.onFinished(); + } return; } else if (DEBUG) { Log.d(TAG, "State changed to: " + state); 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 0db98f372561..c33cc509e816 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java @@ -20,6 +20,7 @@ import android.graphics.Color; import android.os.Trace; import com.android.systemui.statusbar.ScrimView; +import com.android.systemui.statusbar.stack.StackStateAnimator; /** * Possible states of the ScrimController state machine. @@ -38,12 +39,18 @@ public enum ScrimState { @Override public void prepare(ScrimState previousState) { - // DisplayPowerManager will blank the screen, we'll just - // set our scrim to black in this frame to avoid flickering and - // fade it out afterwards. - mBlankScreen = previousState == ScrimState.AOD; + mBlankScreen = false; if (previousState == ScrimState.AOD) { - updateScrimColor(mScrimInFront, 1, Color.BLACK); + mAnimationDuration = StackStateAnimator.ANIMATION_DURATION_WAKEUP; + if (mDisplayRequiresBlanking) { + // DisplayPowerManager will blank the screen, we'll just + // set our scrim to black in this frame to avoid flickering and + // fade it out afterwards. + mBlankScreen = true; + updateScrimColor(mScrimInFront, 1, Color.BLACK); + } + } else { + mAnimationDuration = ScrimController.ANIMATION_DURATION; } mCurrentBehindAlpha = mScrimBehindAlphaKeyguard; mCurrentInFrontAlpha = 0; @@ -78,7 +85,7 @@ public enum ScrimState { AOD { @Override public void prepare(ScrimState previousState) { - if (previousState == ScrimState.PULSING) { + if (previousState == ScrimState.PULSING && !mCanControlScreenOff) { updateScrimColor(mScrimInFront, 1, Color.BLACK); } final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn(); @@ -89,7 +96,7 @@ public enum ScrimState { mCurrentBehindTint = Color.BLACK; // DisplayPowerManager will blank the screen for us, we just need // to set our state. - mAnimateChange = false; + mAnimateChange = mCanControlScreenOff; } }, @@ -103,8 +110,10 @@ public enum ScrimState { mCurrentInFrontAlpha = 0; mCurrentInFrontTint = Color.BLACK; mCurrentBehindTint = Color.BLACK; - mBlankScreen = true; - updateScrimColor(mScrimInFront, 1, Color.BLACK); + mBlankScreen = mDisplayRequiresBlanking; + if (mDisplayRequiresBlanking) { + updateScrimColor(mScrimInFront, 1, Color.BLACK); + } } }, @@ -147,11 +156,15 @@ public enum ScrimState { ScrimView mScrimInFront; ScrimView mScrimBehind; DozeParameters mDozeParameters; + boolean mDisplayRequiresBlanking; + boolean mCanControlScreenOff; public void init(ScrimView scrimInFront, ScrimView scrimBehind, DozeParameters dozeParameters) { mScrimInFront = scrimInFront; mScrimBehind = scrimBehind; mDozeParameters = dozeParameters; + mDisplayRequiresBlanking = dozeParameters.getDisplayNeedsBlanking(); + mCanControlScreenOff = dozeParameters.getCanControlScreenOffAnimation(); } public void prepare(ScrimState previousState) { 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 c61b7e84a318..d162448e09b9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -28,6 +28,9 @@ import static com.android.systemui.statusbar.NotificationLockscreenUserManager .NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION; import static com.android.systemui.statusbar.NotificationLockscreenUserManager.PERMISSION_SELF; import static com.android.systemui.statusbar.NotificationMediaManager.DEBUG_MEDIA; +import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT; +import static com.android.systemui.statusbar.NotificationRemoteInputManager + .FORCE_REMOTE_INPUT_HISTORY; import static com.android.systemui.statusbar.notification.NotificationInflater.InflationCallback; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT; @@ -47,7 +50,6 @@ import android.app.KeyguardManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; -import android.app.RemoteInput; import android.app.StatusBarManager; import android.app.TaskStackBuilder; import android.app.WallpaperColors; @@ -126,7 +128,6 @@ import android.view.accessibility.AccessibilityManager; import android.view.animation.AccelerateInterpolator; import android.widget.DateTimeView; import android.widget.ImageView; -import android.widget.RemoteViews; import android.widget.TextView; import com.android.internal.annotations.VisibleForTesting; @@ -204,6 +205,7 @@ import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationPresenter; +import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.ScrimView; @@ -230,7 +232,6 @@ import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import com.android.systemui.statusbar.policy.PreviewInflater; -import com.android.systemui.statusbar.policy.RemoteInputView; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.UserInfoControllerImpl; import com.android.systemui.statusbar.policy.UserSwitcherController; @@ -250,8 +251,8 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.Stack; +import java.util.function.Function; public class StatusBar extends SystemUI implements DemoMode, DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener, @@ -262,12 +263,8 @@ public class StatusBar extends SystemUI implements DemoMode, ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter { public static final boolean MULTIUSER_DEBUG = false; - public static final boolean ENABLE_REMOTE_INPUT = - SystemProperties.getBoolean("debug.enable_remote_input", true); public static final boolean ENABLE_CHILD_NOTIFICATIONS = SystemProperties.getBoolean("debug.child_notifs", true); - public static final boolean FORCE_REMOTE_INPUT_HISTORY = - SystemProperties.getBoolean("debug.force_remoteinput_history", true); protected static final int MSG_HIDE_RECENT_APPS = 1020; protected static final int MSG_PRELOAD_RECENT_APPS = 1022; @@ -345,14 +342,6 @@ public class StatusBar extends SystemUI implements DemoMode, private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true; /** - * How long to wait before auto-dismissing a notification that was kept for remote input, and - * has now sent a remote input. We auto-dismiss, because the app may not see a reason to cancel - * these given that they technically don't exist anymore. We wait a bit in case the app issues - * an update. - */ - private static final int REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY = 200; - - /** * Never let the alpha become zero for surfaces that draw with SRC - otherwise the RenderNode * won't draw anything and uninitialized memory will show through * if mScrimSrcModeEnabled. Note that 0.001 is rounded down to 0 in @@ -540,6 +529,7 @@ public class StatusBar extends SystemUI implements DemoMode, private NotificationMediaManager mMediaManager; protected NotificationLockscreenUserManager mLockscreenUserManager; + protected NotificationRemoteInputManager mRemoteInputManager; /** Keys of notifications currently visible to the user. */ private final ArraySet<NotificationVisibility> mCurrentlyVisibleNotifications = @@ -656,7 +646,9 @@ public class StatusBar extends SystemUI implements DemoMode, + "mStatusBarKeyguardViewManager was null"); return; } - mStatusBarKeyguardViewManager.onKeyguardFadedAway(); + if (mKeyguardFadingAway) { + mStatusBarKeyguardViewManager.onKeyguardFadedAway(); + } } @Override @@ -723,6 +715,7 @@ public class StatusBar extends SystemUI implements DemoMode, @Override public void start() { + mRemoteInputManager = Dependency.get(NotificationRemoteInputManager.class); mNetworkController = Dependency.get(NetworkController.class); mUserSwitcherController = Dependency.get(UserSwitcherController.class); mScreenLifecycle = Dependency.get(ScreenLifecycle.class); @@ -777,7 +770,6 @@ public class StatusBar extends SystemUI implements DemoMode, mRecents = getComponent(Recents.class); - mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); mLockPatternUtils = new LockPatternUtils(mContext); @@ -817,7 +809,7 @@ public class StatusBar extends SystemUI implements DemoMode, } // Set up the initial notification state. - mNotificationListener = new NotificationListener(this, mContext); + mNotificationListener = new NotificationListener(this, mRemoteInputManager, mContext); mNotificationListener.register(); if (DEBUG) { @@ -1159,7 +1151,7 @@ public class StatusBar extends SystemUI implements DemoMode, protected View.OnTouchListener getStatusBarWindowTouchListener() { return (v, event) -> { checkUserAutohide(event); - checkRemoteInputOutside(event); + mRemoteInputManager.checkRemoteInputOutside(event); if (event.getAction() == MotionEvent.ACTION_DOWN) { if (mExpandedVisible) { animateCollapsePanels(); @@ -1432,31 +1424,7 @@ public class StatusBar extends SystemUI implements DemoMode, mKeyguardIndicationController .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); mFingerprintUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); - mRemoteInputController.addCallback(mStatusBarKeyguardViewManager); - - mRemoteInputController.addCallback(new RemoteInputController.Callback() { - @Override - public void onRemoteInputSent(Entry entry) { - if (FORCE_REMOTE_INPUT_HISTORY && mKeysKeptForRemoteInput.contains(entry.key)) { - removeNotification(entry.key, null); - } else if (mRemoteInputEntriesToRemoveOnCollapse.contains(entry)) { - // We're currently holding onto this notification, but from the apps point of - // view it is already canceled, so we'll need to cancel it on the apps behalf - // after sending - unless the app posts an update in the mean time, so wait a - // bit. - mHandler.postDelayed(() -> { - if (mRemoteInputEntriesToRemoveOnCollapse.remove(entry)) { - removeNotification(entry.key, null); - } - }, REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY); - } - try { - mBarService.onNotificationDirectReplied(entry.key); - } catch (RemoteException e) { - // system process is dead if we're here. - } - } - }); + mRemoteInputManager.getController().addCallback(mStatusBarKeyguardViewManager); mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback(); mLightBarController.setFingerprintUnlockController(mFingerprintUnlockController); @@ -1633,7 +1601,7 @@ public class StatusBar extends SystemUI implements DemoMode, // sending look longer than it takes. // Also we should not defer the removal if reordering isn't allowed since otherwise // some notifications can't disappear before the panel is closed. - boolean ignoreEarliestRemovalTime = mRemoteInputController.isSpinning(key) + boolean ignoreEarliestRemovalTime = mRemoteInputManager.getController().isSpinning(key) && !FORCE_REMOTE_INPUT_HISTORY || !mVisualStabilityManager.isReorderingAllowed(); deferRemoval = !mHeadsUpManager.removeNotification(key, ignoreEarliestRemovalTime); @@ -1641,7 +1609,7 @@ public class StatusBar extends SystemUI implements DemoMode, mMediaManager.onNotificationRemoved(key); Entry entry = mNotificationData.get(key); - if (FORCE_REMOTE_INPUT_HISTORY && mRemoteInputController.isSpinning(key) + if (FORCE_REMOTE_INPUT_HISTORY && mRemoteInputManager.getController().isSpinning(key) && entry.row != null && !entry.row.isDismissed()) { StatusBarNotification sbn = entry.notification; @@ -1679,7 +1647,7 @@ public class StatusBar extends SystemUI implements DemoMode, } if (updated) { Log.w(TAG, "Keeping notification around after sending remote input "+ entry.key); - mKeysKeptForRemoteInput.add(entry.key); + mRemoteInputManager.getKeysKeptForRemoteInput().add(entry.key); return; } } @@ -1689,12 +1657,11 @@ public class StatusBar extends SystemUI implements DemoMode, return; } - if (entry != null && mRemoteInputController.isRemoteInputActive(entry) - && (entry.row != null && !entry.row.isDismissed())) { + if (mRemoteInputManager.onRemoveNotification(entry)) { mLatestRankingMap = ranking; - mRemoteInputEntriesToRemoveOnCollapse.add(entry); return; } + if (entry != null && mGutsManager.getExposedGuts() != null && mGutsManager.getExposedGuts() == entry.row.getGuts() && entry.row.getGuts() != null && !entry.row.getGuts().isLeavebehind()) { @@ -1768,9 +1735,7 @@ public class StatusBar extends SystemUI implements DemoMode, protected void performRemoveNotification(StatusBarNotification n) { Entry entry = mNotificationData.get(n.getKey()); - if (mRemoteInputController.isRemoteInputActive(entry)) { - mRemoteInputController.removeRemoteInput(entry, null); - } + mRemoteInputManager.onPerformRemoveNotification(n, entry); // start old BaseStatusBar.performRemoveNotification. final String pkg = n.getPackageName(); final String tag = n.getTag(); @@ -1783,12 +1748,7 @@ public class StatusBar extends SystemUI implements DemoMode, } else if (mStackScroller.hasPulsingNotifications()) { dismissalSurface = NotificationStats.DISMISSAL_AOD; } - mBarService.onNotificationClear(pkg, tag, id, userId, n.getKey(), - dismissalSurface); - if (FORCE_REMOTE_INPUT_HISTORY - && mKeysKeptForRemoteInput.contains(n.getKey())) { - mKeysKeptForRemoteInput.remove(n.getKey()); - } + mBarService.onNotificationClear(pkg, tag, id, userId, n.getKey(), dismissalSurface); removeNotification(n.getKey(), null); } catch (RemoteException ex) { @@ -2507,7 +2467,7 @@ public class StatusBar extends SystemUI implements DemoMode, mStatusBarWindowManager.setHeadsUpShowing(false); mHeadsUpManager.setHeadsUpGoingAway(false); } - removeRemoteInputEntriesKeptUntilCollapsed(); + mRemoteInputManager.removeRemoteInputEntriesKeptUntilCollapsed(); }); } } @@ -2586,19 +2546,10 @@ public class StatusBar extends SystemUI implements DemoMode, } if (!isExpanded) { - removeRemoteInputEntriesKeptUntilCollapsed(); + mRemoteInputManager.removeRemoteInputEntriesKeptUntilCollapsed(); } } - private void removeRemoteInputEntriesKeptUntilCollapsed() { - for (int i = 0; i < mRemoteInputEntriesToRemoveOnCollapse.size(); i++) { - Entry entry = mRemoteInputEntriesToRemoveOnCollapse.valueAt(i); - mRemoteInputController.removeRemoteInput(entry, null); - removeNotification(entry.key, mLatestRankingMap); - } - mRemoteInputEntriesToRemoveOnCollapse.clear(); - } - public NotificationStackScrollLayout getNotificationScrollLayout() { return mStackScroller; } @@ -3182,19 +3133,12 @@ public class StatusBar extends SystemUI implements DemoMode, if ((mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT) != 0 // a transient bar is revealed && event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar && event.getX() == 0 && event.getY() == 0 // a touch outside both bars - && !mRemoteInputController.isRemoteInputActive()) { // not due to typing in IME + && !mRemoteInputManager.getController() + .isRemoteInputActive()) { // not due to typing in IME userAutohide(); } } - private void checkRemoteInputOutside(MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar - && event.getX() == 0 && event.getY() == 0 // a touch outside both bars - && mRemoteInputController.isRemoteInputActive()) { - mRemoteInputController.closeRemoteInputs(); - } - } - private void userAutohide() { cancelAutohide(); mHandler.postDelayed(mAutohide, 350); // longer than app gesture -> flag clear @@ -3375,18 +3319,18 @@ public class StatusBar extends SystemUI implements DemoMode, private void addStatusBarWindow() { makeStatusBarView(); mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class); - mRemoteInputController = new RemoteInputController(new RemoteInputController.Delegate() { - public void setRemoteInputActive(NotificationData.Entry entry, - boolean remoteInputActive) { - mHeadsUpManager.setRemoteInputActive(entry, remoteInputActive); - } - public void lockScrollTo(NotificationData.Entry entry) { - mStackScroller.lockScrollTo(entry.row); - } - public void requestDisallowLongPressAndDismiss() { - mStackScroller.requestDisallowLongPress(); - mStackScroller.requestDisallowDismiss(); - } + mRemoteInputManager.setUpWithPresenter(this, this, new RemoteInputController.Delegate() { + public void setRemoteInputActive(NotificationData.Entry entry, + boolean remoteInputActive) { + mHeadsUpManager.setRemoteInputActive(entry, remoteInputActive); + } + public void lockScrollTo(NotificationData.Entry entry) { + mStackScroller.lockScrollTo(entry.row); + } + public void requestDisallowLongPressAndDismiss() { + mStackScroller.requestDisallowLongPress(); + mStackScroller.requestDisallowDismiss(); + } }); mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight()); } @@ -3506,8 +3450,8 @@ public class StatusBar extends SystemUI implements DemoMode, String action = intent.getAction(); if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { KeyboardShortcuts.dismiss(); - if (mRemoteInputController != null) { - mRemoteInputController.closeRemoteInputs(); + if (mRemoteInputManager.getController() != null) { + mRemoteInputManager.getController().closeRemoteInputs(); } if (mLockscreenUserManager.isCurrentProfile(getSendingUserId())) { int flags = CommandQueue.FLAG_EXCLUDE_NONE; @@ -4407,7 +4351,8 @@ public class StatusBar extends SystemUI implements DemoMode, private void updateDozingState() { Trace.traceCounter(Trace.TRACE_TAG_APP, "dozing", mDozing ? 1 : 0); Trace.beginSection("StatusBar#updateDozingState"); - boolean animate = !mDozing && mDozeServiceHost.shouldAnimateWakeup(); + boolean animate = (!mDozing && mDozeServiceHost.shouldAnimateWakeup()) + || (mDozing && mDozeServiceHost.shouldAnimateScreenOff()); mNotificationPanel.setDozing(mDozing, animate); mStackScroller.setDark(mDozing, animate, mWakeUpTouchLocation); mDozeScrimController.setDozing(mDozing); @@ -4544,7 +4489,7 @@ public class StatusBar extends SystemUI implements DemoMode, clearNotificationEffects(); } if (state == StatusBarState.KEYGUARD) { - removeRemoteInputEntriesKeptUntilCollapsed(); + mRemoteInputManager.removeRemoteInputEntriesKeptUntilCollapsed(); maybeEscalateHeadsUp(); } mState = state; @@ -4748,13 +4693,15 @@ public class StatusBar extends SystemUI implements DemoMode, dismissKeyguardThenExecute(dismissAction, true /* afterKeyguardGone */); } - protected void onLockedRemoteInput(ExpandableNotificationRow row, View clicked) { + @Override + public void onLockedRemoteInput(ExpandableNotificationRow row, View clicked) { mLeaveOpenOnKeyguardHide = true; showBouncer(); mPendingRemoteInputView = clicked; } - protected void onMakeExpandedVisibleForRemoteInput(ExpandableNotificationRow row, + @Override + public void onMakeExpandedVisibleForRemoteInput(ExpandableNotificationRow row, View clickedView) { if (isKeyguardShowing()) { onLockedRemoteInput(row, clickedView); @@ -4764,6 +4711,47 @@ public class StatusBar extends SystemUI implements DemoMode, } } + @Override + public boolean shouldHandleRemoteInput(View view, PendingIntent pendingIntent) { + // Skip remote input as doing so will expand the notification shade. + return (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0; + } + + @Override + public boolean handleRemoteViewClick(View view, PendingIntent pendingIntent, + Intent fillInIntent, NotificationRemoteInputManager.ClickHandler defaultHandler) { + final boolean isActivity = pendingIntent.isActivity(); + if (isActivity) { + final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity( + mContext, pendingIntent.getIntent(), mLockscreenUserManager.getCurrentUserId()); + dismissKeyguardThenExecute(() -> { + try { + ActivityManager.getService().resumeAppSwitches(); + } catch (RemoteException e) { + } + + boolean handled = defaultHandler.handleClick(); + + // close the shade if it was open + if (handled && !mNotificationPanel.isFullyCollapsed()) { + animateCollapsePanels( + CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */); + visibilityChanged(false); + mAssistManager.hideAssist(); + + // Wait for activity start. + return true; + } else { + return false; + } + + }, afterKeyguardGone); + return true; + } else { + return defaultHandler.handleClick(); + } + } + protected boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender, String notificationKey) { // Clear pending remote view, as we do not want to trigger pending remote input view when @@ -4800,7 +4788,8 @@ public class StatusBar extends SystemUI implements DemoMode, // End old BaseStatusBar.startWorkChallengeIfNecessary. } - protected void onLockedWorkRemoteInput(int userId, ExpandableNotificationRow row, + @Override + public void onLockedWorkRemoteInput(int userId, ExpandableNotificationRow row, View clicked) { // Collapse notification and show work challenge animateCollapsePanels(); @@ -5026,6 +5015,7 @@ public class StatusBar extends SystemUI implements DemoMode, return !mNotificationData.getActiveNotifications().isEmpty(); } + @Override public void wakeUpIfDozing(long time, View where) { if (mDozing) { PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); @@ -5040,6 +5030,11 @@ public class StatusBar extends SystemUI implements DemoMode, } @Override + public boolean isDeviceLocked(int userId) { + return mKeyguardManager.isDeviceLocked(userId); + } + + @Override public void appTransitionCancelled() { EventBus.getDefault().send(new AppTransitionFinishedEvent()); } @@ -5146,7 +5141,15 @@ public class StatusBar extends SystemUI implements DemoMode, Trace.endSection(); } - public void updateScrimController() { + @VisibleForTesting + void updateScrimController() { + Trace.beginSection("StatusBar#updateScrimController"); + + // We don't want to end up in KEYGUARD state when we're unlocking with + // fingerprint from doze. We should cross fade directly from black. + final boolean wakeAndUnlocking = mFingerprintUnlockController.getMode() + == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK; + if (mBouncerShowing) { mScrimController.transitionTo(ScrimState.BOUNCER); } else if (mLaunchCameraOnScreenTurningOn || isInLaunchTransition()) { @@ -5157,11 +5160,12 @@ public class StatusBar extends SystemUI implements DemoMode, // Handled in DozeScrimController#setPulsing } else if (mDozing) { mScrimController.transitionTo(ScrimState.AOD); - } else if (mIsKeyguard) { + } else if (mIsKeyguard && !wakeAndUnlocking) { mScrimController.transitionTo(ScrimState.KEYGUARD); } else { mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback); } + Trace.endSection(); } public boolean isKeyguardShowing() { @@ -5175,6 +5179,7 @@ public class StatusBar extends SystemUI implements DemoMode, private final class DozeServiceHost implements DozeHost { private final ArrayList<Callback> mCallbacks = new ArrayList<>(); private boolean mAnimateWakeup; + private boolean mAnimateScreenOff; private boolean mIgnoreTouchWhilePulsing; @Override @@ -5322,6 +5327,11 @@ public class StatusBar extends SystemUI implements DemoMode, } @Override + public void setAnimateScreenOff(boolean animateScreenOff) { + mAnimateScreenOff = animateScreenOff; + } + + @Override public void onDoubleTap(float screenX, float screenY) { if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null && mAmbientIndicationContainer.getVisibility() == View.VISIBLE) { @@ -5365,6 +5375,10 @@ public class StatusBar extends SystemUI implements DemoMode, private boolean shouldAnimateWakeup() { return mAnimateWakeup; } + + public boolean shouldAnimateScreenOff() { + return mAnimateScreenOff; + } } public boolean shouldIgnoreTouch() { @@ -5382,7 +5396,6 @@ public class StatusBar extends SystemUI implements DemoMode, protected final NotificationGroupManager mGroupManager = new NotificationGroupManager(); - protected RemoteInputController mRemoteInputController; // for heads up notifications protected HeadsUpManager mHeadsUpManager; @@ -5399,14 +5412,6 @@ public class StatusBar extends SystemUI implements DemoMode, protected boolean mVisible; protected final ArraySet<Entry> mHeadsUpEntriesToRemoveOnSwitch = new ArraySet<>(); - protected final ArraySet<Entry> mRemoteInputEntriesToRemoveOnCollapse = new ArraySet<>(); - - /** - * Notifications with keys in this set are not actually around anymore. We kept them around - * when they were canceled in response to a remote input interaction. This allows us to show - * what you replied and allows you to continue typing into it. - */ - protected final ArraySet<String> mKeysKeptForRemoteInput = new ArraySet<>(); // mScreenOnFromKeyguard && mVisible. private boolean mVisibleToUser; @@ -5418,8 +5423,6 @@ public class StatusBar extends SystemUI implements DemoMode, protected PowerManager mPowerManager; protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; - private UserManager mUserManager; - protected KeyguardManager mKeyguardManager; private LockPatternUtils mLockPatternUtils; private DeviceProvisionedController mDeviceProvisionedController @@ -5473,212 +5476,6 @@ public class StatusBar extends SystemUI implements DemoMode, } }; - private final RemoteViews.OnClickHandler mOnClickHandler = new RemoteViews.OnClickHandler() { - - @Override - public boolean onClickHandler( - final View view, final PendingIntent pendingIntent, final Intent fillInIntent) { - wakeUpIfDozing(SystemClock.uptimeMillis(), view); - - if (handleRemoteInput(view, pendingIntent)) { - return true; - } - - if (DEBUG) { - Log.v(TAG, "Notification click handler invoked for intent: " + pendingIntent); - } - logActionClick(view); - // The intent we are sending is for the application, which - // won't have permission to immediately start an activity after - // the user switches to home. We know it is safe to do at this - // point, so make sure new activity switches are now allowed. - try { - ActivityManager.getService().resumeAppSwitches(); - } catch (RemoteException e) { - } - final boolean isActivity = pendingIntent.isActivity(); - if (isActivity) { - final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity( - mContext, pendingIntent.getIntent(), - mLockscreenUserManager.getCurrentUserId()); - dismissKeyguardThenExecute(() -> { - try { - ActivityManager.getService().resumeAppSwitches(); - } catch (RemoteException e) { - } - - boolean handled = superOnClickHandler(view, pendingIntent, fillInIntent); - - // close the shade if it was open - if (handled && !mNotificationPanel.isFullyCollapsed()) { - animateCollapsePanels( - CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */); - visibilityChanged(false); - mAssistManager.hideAssist(); - - // Wait for activity start. - return true; - } else { - return false; - } - - }, afterKeyguardGone); - return true; - } else { - return superOnClickHandler(view, pendingIntent, fillInIntent); - } - } - - private void logActionClick(View view) { - ViewParent parent = view.getParent(); - String key = getNotificationKeyForParent(parent); - if (key == null) { - Log.w(TAG, "Couldn't determine notification for click."); - return; - } - int index = -1; - // If this is a default template, determine the index of the button. - if (view.getId() == com.android.internal.R.id.action0 && - parent != null && parent instanceof ViewGroup) { - ViewGroup actionGroup = (ViewGroup) parent; - index = actionGroup.indexOfChild(view); - } - try { - mBarService.onNotificationActionClick(key, index); - } catch (RemoteException e) { - // Ignore - } - } - - private String getNotificationKeyForParent(ViewParent parent) { - while (parent != null) { - if (parent instanceof ExpandableNotificationRow) { - return ((ExpandableNotificationRow) parent).getStatusBarNotification().getKey(); - } - parent = parent.getParent(); - } - return null; - } - - private boolean superOnClickHandler(View view, PendingIntent pendingIntent, - Intent fillInIntent) { - return super.onClickHandler(view, pendingIntent, fillInIntent, - WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY); - } - - private boolean handleRemoteInput(View view, PendingIntent pendingIntent) { - if ((mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0) { - // Skip remote input as doing so will expand the notification shade. - return true; - } - - Object tag = view.getTag(com.android.internal.R.id.remote_input_tag); - RemoteInput[] inputs = null; - if (tag instanceof RemoteInput[]) { - inputs = (RemoteInput[]) tag; - } - - if (inputs == null) { - return false; - } - - RemoteInput input = null; - - for (RemoteInput i : inputs) { - if (i.getAllowFreeFormInput()) { - input = i; - } - } - - if (input == null) { - return false; - } - - ViewParent p = view.getParent(); - RemoteInputView riv = null; - while (p != null) { - if (p instanceof View) { - View pv = (View) p; - if (pv.isRootNamespace()) { - riv = findRemoteInputView(pv); - break; - } - } - p = p.getParent(); - } - ExpandableNotificationRow row = null; - while (p != null) { - if (p instanceof ExpandableNotificationRow) { - row = (ExpandableNotificationRow) p; - break; - } - p = p.getParent(); - } - - if (row == null) { - return false; - } - - row.setUserExpanded(true); - - if (!mLockscreenUserManager.shouldAllowLockscreenRemoteInput()) { - final int userId = pendingIntent.getCreatorUserHandle().getIdentifier(); - if (mLockscreenUserManager.isLockscreenPublicMode(userId)) { - onLockedRemoteInput(row, view); - return true; - } - if (mUserManager.getUserInfo(userId).isManagedProfile() - && mKeyguardManager.isDeviceLocked(userId)) { - onLockedWorkRemoteInput(userId, row, view); - return true; - } - } - - if (riv == null) { - riv = findRemoteInputView(row.getPrivateLayout().getExpandedChild()); - if (riv == null) { - return false; - } - if (!row.getPrivateLayout().getExpandedChild().isShown()) { - onMakeExpandedVisibleForRemoteInput(row, view); - return true; - } - } - - int width = view.getWidth(); - if (view instanceof TextView) { - // Center the reveal on the text which might be off-center from the TextView - TextView tv = (TextView) view; - if (tv.getLayout() != null) { - int innerWidth = (int) tv.getLayout().getLineWidth(0); - innerWidth += tv.getCompoundPaddingLeft() + tv.getCompoundPaddingRight(); - width = Math.min(width, innerWidth); - } - } - int cx = view.getLeft() + width / 2; - int cy = view.getTop() + view.getHeight() / 2; - int w = riv.getWidth(); - int h = riv.getHeight(); - int r = Math.max( - Math.max(cx + cy, cx + (h - cy)), - Math.max((w - cx) + cy, (w - cx) + (h - cy))); - - riv.setRevealParameters(cx, cy, r); - riv.setPendingIntent(pendingIntent); - riv.setRemoteInput(inputs, input); - riv.focusAnimated(); - - return true; - } - - private RemoteInputView findRemoteInputView(View v) { - if (v == null) { - return null; - } - return (RemoteInputView) v.findViewWithTag(RemoteInputView.VIEW_TAG); - } - }; - private final BroadcastReceiver mBannerActionBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -5923,12 +5720,11 @@ public class StatusBar extends SystemUI implements DemoMode, row.setGroupManager(mGroupManager); row.setHeadsUpManager(mHeadsUpManager); row.setAboveShelfChangedListener(mAboveShelfObserver); - row.setRemoteInputController(mRemoteInputController); row.setOnExpandClickListener(this); - row.setRemoteViewClickHandler(mOnClickHandler); row.setInflationCallback(this); row.setSecureStateProvider(this::isKeyguardCurrentlySecure); row.setLongPressListener(getNotificationLongClicker()); + mRemoteInputManager.bindRow(row); // Get the app name. // Note that Notification.Builder#bindHeaderAppName has similar logic @@ -6390,7 +6186,8 @@ public class StatusBar extends SystemUI implements DemoMode, return; } mHeadsUpEntriesToRemoveOnSwitch.remove(entry); - mRemoteInputEntriesToRemoveOnCollapse.remove(entry); + mRemoteInputManager.onUpdateNotification(entry); + if (key.equals(mGutsManager.getKeyToRemoveOnGutsClosed())) { mGutsManager.setKeyToRemoveOnGutsClosed(null); Log.w(TAG, "Notification that was kept for guts was updated. " + key); @@ -6635,11 +6432,6 @@ public class StatusBar extends SystemUI implements DemoMode, return mLatestRankingMap; } - @Override - public Set<String> getKeysKeptForRemoteInput() { - return mKeysKeptForRemoteInput; - } - private final NotificationInfo.CheckSaveListener mCheckSaveListener = (Runnable saveImportance, StatusBarNotification sbn) -> { // If the user has security enabled, show challenge if the setting is changed. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index dacd3d935d0a..8504d8e5fee5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -380,8 +380,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mStatusBar.fadeKeyguardWhilePulsing(); wakeAndUnlockDejank(); } else { - mFingerprintUnlockController.startKeyguardFadingAway(); - mStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration); boolean staying = mStatusBar.hideKeyguard(); if (!staying) { mStatusBarWindowManager.setKeyguardFadingAway(true); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java index ed96b4115888..b0b5b8ec1e09 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.phone; +import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT; + import android.app.ActivityManager; import android.app.IActivityManager; import android.content.Context; @@ -156,7 +158,7 @@ public class StatusBarWindowManager implements RemoteInputController.Callback, D private void applyFocusableFlag(State state) { boolean panelFocusable = state.statusBarFocusable && state.panelExpanded; if (state.bouncerShowing && (state.keyguardOccluded || state.keyguardNeedsInput) - || StatusBar.ENABLE_REMOTE_INPUT && state.remoteInputActive) { + || ENABLE_REMOTE_INPUT && state.remoteInputActive) { mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index 0f2a2c8b2bc2..fe39a894a094 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -3681,6 +3681,7 @@ public class NotificationStackScrollLayout extends ViewGroup mHideSensitiveNeedsAnimation = true; mNeedsAnimation = true; } + updateContentHeight(); requestChildrenUpdate(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java index 195607dce81f..7374f115a19b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java @@ -448,7 +448,7 @@ public class StackScrollAlgorithm { childState.height = Math.max(row.getIntrinsicHeight(), childState.height); childState.hidden = false; ExpandableViewState topState = resultState.getViewStateForView(topHeadsUpEntry); - if (!isTopEntry && (!mIsExpanded + if (topState != null && !isTopEntry && (!mIsExpanded || unmodifiedEndLocation < topState.yTranslation + topState.height)) { // Ensure that a headsUp doesn't vertically extend further than the heads-up at // the top most z-position diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java index f78a718eff9f..236c348e539b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java @@ -40,7 +40,7 @@ import java.util.Stack; public class StackStateAnimator { public static final int ANIMATION_DURATION_STANDARD = 360; - public static final int ANIMATION_DURATION_WAKEUP = 200; + public static final int ANIMATION_DURATION_WAKEUP = 500; public static final int ANIMATION_DURATION_GO_TO_FULL_SHADE = 448; public static final int ANIMATION_DURATION_APPEAR_DISAPPEAR = 464; public static final int ANIMATION_DURATION_DIMMED_ACTIVATED = 220; diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 3e70980fdc67..7959b72ce7b3 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -29,11 +29,15 @@ import android.app.Dialog; import android.app.KeyguardManager; import android.content.Context; import android.content.DialogInterface; +import android.content.pm.PackageManager; import android.content.res.ColorStateList; import android.content.res.Resources; import android.graphics.Color; import android.graphics.Rect; +import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.TransitionDrawable; import android.media.AudioManager; import android.media.AudioSystem; import android.os.Debug; @@ -42,6 +46,8 @@ import android.os.Looper; import android.os.Message; import android.os.SystemClock; import android.provider.Settings.Global; +import android.transition.AutoTransition; +import android.transition.TransitionManager; import android.util.Log; import android.util.Slog; import android.util.SparseBooleanArray; @@ -66,6 +72,7 @@ import android.widget.TextView; import com.android.settingslib.Utils; import com.android.systemui.Dependency; +import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.plugins.VolumeDialog; import com.android.systemui.plugins.VolumeDialogController; @@ -97,7 +104,7 @@ public class VolumeDialogImpl implements VolumeDialog { private CustomDialog mDialog; private ViewGroup mDialogView; private ViewGroup mDialogRowsView; - private ViewGroup mDialogContentView; + private ImageButton mExpandButton; private ImageButton mRingerIcon; private TextView mRingerStatus; private final List<VolumeRow> mRows = new ArrayList<>(); @@ -109,9 +116,10 @@ public class VolumeDialogImpl implements VolumeDialog { private final Accessibility mAccessibility = new Accessibility(); private final ColorStateList mActiveSliderTint; private final ColorStateList mInactiveSliderTint; - private VolumeUiLayout mHardwareLayout; private boolean mShowing; + private boolean mExpanded; + private boolean mExpandButtonAnimationRunning; private boolean mShowA11yStream; private int mActiveStream; @@ -170,57 +178,57 @@ public class VolumeDialogImpl implements VolumeDialog { mWindow.setWindowAnimations(com.android.internal.R.style.Animation_Toast); mDialog.setContentView(R.layout.volume_dialog); - mDialog.setOnShowListener(new DialogInterface.OnShowListener() { - @Override - public void onShow(DialogInterface dialog) { - mDialogView.setTranslationY(-mDialogView.getHeight()); - mDialogView.setAlpha(0); - mDialogView.animate() - .alpha(1) - .translationY(0) - .setDuration(300) - .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator()) - .withEndAction(() -> { - mWindow.getDecorView().requestAccessibilityFocus(); - }) - .start(); - } + mDialog.setOnShowListener(dialog -> { + mDialogView.setTranslationY(-mDialogView.getHeight()); + mDialogView.setAlpha(0); + mDialogView.animate() + .alpha(1) + .translationY(0) + .setDuration(300) + .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator()) + .withEndAction(() -> { + mWindow.getDecorView().requestAccessibilityFocus(); + }) + .start(); }); mDialogView = mDialog.findViewById(R.id.volume_dialog); - mDialogView.setOnHoverListener(new View.OnHoverListener() { - @Override - public boolean onHover(View v, MotionEvent event) { - int action = event.getActionMasked(); - mHovering = (action == MotionEvent.ACTION_HOVER_ENTER) - || (action == MotionEvent.ACTION_HOVER_MOVE); - rescheduleTimeoutH(); - return true; - } + mDialogView.setOnHoverListener((v, event) -> { + int action = event.getActionMasked(); + mHovering = (action == MotionEvent.ACTION_HOVER_ENTER) + || (action == MotionEvent.ACTION_HOVER_MOVE); + rescheduleTimeoutH(); + return true; }); - mHardwareLayout = VolumeUiLayout.get(mDialogView); - mHardwareLayout.setOutsideTouchListener(view -> dismiss(DISMISS_REASON_TOUCH_OUTSIDE)); + VolumeUiLayout hardwareLayout = VolumeUiLayout.get(mDialogView); + hardwareLayout.setOutsideTouchListener(view -> dismiss(DISMISS_REASON_TOUCH_OUTSIDE)); + + ViewGroup dialogContentView = mDialog.findViewById(R.id.volume_dialog_content); + mDialogRowsView = dialogContentView.findViewById(R.id.volume_dialog_rows); + mRingerIcon = mDialog.findViewById(R.id.ringer_icon); + mRingerStatus = mDialog.findViewById(R.id.ringer_status); - mDialogContentView = mDialog.findViewById(R.id.volume_dialog_content); - mDialogRowsView = mDialogContentView.findViewById(R.id.volume_dialog_rows); - mRingerIcon = mDialogContentView.findViewById(R.id.ringer_icon); - mRingerStatus = mDialogContentView.findViewById(R.id.ringer_status); + mExpanded = false; + mExpandButton = mDialogView.findViewById(R.id.volume_expand_button); + mExpandButton.setOnClickListener(mClickExpand); + mExpandButton.setVisibility( + AudioSystem.isSingleVolume(mContext) ? View.GONE : View.VISIBLE); if (mRows.isEmpty()) { addRow(AudioManager.STREAM_MUSIC, - R.drawable.ic_volume_media, R.drawable.ic_volume_media_mute, true); + R.drawable.ic_volume_media, R.drawable.ic_volume_media_mute, true, true); if (!AudioSystem.isSingleVolume(mContext)) { addRow(AudioManager.STREAM_RING, - R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, false); + R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, true, false); addRow(AudioManager.STREAM_ALARM, - R.drawable.ic_volume_alarm, R.drawable.ic_volume_alarm_mute, false); + R.drawable.ic_volume_alarm, R.drawable.ic_volume_alarm_mute, true, false); addRow(AudioManager.STREAM_VOICE_CALL, - R.drawable.ic_volume_voice, R.drawable.ic_volume_voice, false); + R.drawable.ic_volume_voice, R.drawable.ic_volume_voice, false, false); addRow(AudioManager.STREAM_BLUETOOTH_SCO, - R.drawable.ic_volume_bt_sco, R.drawable.ic_volume_bt_sco, false); - addRow(AudioManager.STREAM_SYSTEM, - R.drawable.ic_volume_system, R.drawable.ic_volume_system_mute, false); + R.drawable.ic_volume_bt_sco, R.drawable.ic_volume_bt_sco, false, false); + addRow(AudioManager.STREAM_SYSTEM, R.drawable.ic_volume_system, + R.drawable.ic_volume_system_mute, false, false); addRow(AudioManager.STREAM_ACCESSIBILITY, R.drawable.ic_volume_accessibility, - R.drawable.ic_volume_accessibility, true); + R.drawable.ic_volume_accessibility, true, false); } } else { addExistingRows(); @@ -249,14 +257,15 @@ public class VolumeDialogImpl implements VolumeDialog { mHandler.sendEmptyMessage(H.RECHECK_ALL); } - private void addRow(int stream, int iconRes, int iconMuteRes, boolean important) { - addRow(stream, iconRes, iconMuteRes, important, false); + private void addRow(int stream, int iconRes, int iconMuteRes, boolean important, + boolean defaultStream) { + addRow(stream, iconRes, iconMuteRes, important, defaultStream, false); } private void addRow(int stream, int iconRes, int iconMuteRes, boolean important, - boolean dynamic) { + boolean defaultStream, boolean dynamic) { VolumeRow row = new VolumeRow(); - initRow(row, stream, iconRes, iconMuteRes, important); + initRow(row, stream, iconRes, iconMuteRes, important, defaultStream); int rowSize; int viewSize; if (mShowA11yStream && dynamic && (rowSize = mRows.size()) > 1 @@ -274,7 +283,8 @@ public class VolumeDialogImpl implements VolumeDialog { int N = mRows.size(); for (int i = 0; i < N; i++) { final VolumeRow row = mRows.get(i); - initRow(row, row.stream, row.iconRes, row.iconMuteRes, row.important); + initRow(row, row.stream, row.iconRes, row.iconMuteRes, row.important, + row.defaultStream); mDialogRowsView.addView(row.view); updateVolumeRowH(row); } @@ -299,6 +309,7 @@ public class VolumeDialogImpl implements VolumeDialog { public void dump(PrintWriter writer) { writer.println(VolumeDialogImpl.class.getSimpleName() + " state:"); writer.print(" mShowing: "); writer.println(mShowing); + writer.print(" mExpanded: "); writer.println(mExpanded); writer.print(" mActiveStream: "); writer.println(mActiveStream); writer.print(" mDynamic: "); writer.println(mDynamic); writer.print(" mAutomute: "); writer.println(mAutomute); @@ -317,11 +328,12 @@ public class VolumeDialogImpl implements VolumeDialog { @SuppressLint("InflateParams") private void initRow(final VolumeRow row, final int stream, int iconRes, int iconMuteRes, - boolean important) { + boolean important, boolean defaultStream) { row.stream = stream; row.iconRes = iconRes; row.iconMuteRes = iconMuteRes; row.important = important; + row.defaultStream = defaultStream; row.view = mDialog.getLayoutInflater().inflate(R.layout.volume_dialog_row, null); row.view.setId(row.stream); row.view.setTag(row); @@ -359,34 +371,31 @@ public class VolumeDialogImpl implements VolumeDialog { row.icon = row.view.findViewById(R.id.volume_row_icon); row.icon.setImageResource(iconRes); if (row.stream != AudioSystem.STREAM_ACCESSIBILITY) { - row.icon.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Events.writeEvent(mContext, Events.EVENT_ICON_CLICK, row.stream, row.iconState); - mController.setActiveStream(row.stream); - if (row.stream == AudioManager.STREAM_RING) { - final boolean hasVibrator = mController.hasVibrator(); - if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) { - if (hasVibrator) { - mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false); - } else { - final boolean wasZero = row.ss.level == 0; - mController.setStreamVolume(stream, - wasZero ? row.lastAudibleLevel : 0); - } + row.icon.setOnClickListener(v -> { + Events.writeEvent(mContext, Events.EVENT_ICON_CLICK, row.stream, row.iconState); + mController.setActiveStream(row.stream); + if (row.stream == AudioManager.STREAM_RING) { + final boolean hasVibrator = mController.hasVibrator(); + if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) { + if (hasVibrator) { + mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false); } else { - mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false); - if (row.ss.level == 0) { - mController.setStreamVolume(stream, 1); - } + final boolean wasZero = row.ss.level == 0; + mController.setStreamVolume(stream, + wasZero ? row.lastAudibleLevel : 0); } } else { - final boolean vmute = row.ss.level == row.ss.levelMin; - mController.setStreamVolume(stream, - vmute ? row.lastAudibleLevel : row.ss.levelMin); + mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false); + if (row.ss.level == 0) { + mController.setStreamVolume(stream, 1); + } } - row.userAttempt = 0; // reset the grace period, slider updates immediately + } else { + final boolean vmute = row.ss.level == row.ss.levelMin; + mController.setStreamVolume(stream, + vmute ? row.lastAudibleLevel : row.ss.levelMin); } + row.userAttempt = 0; // reset the grace period, slider updates immediately }); } else { row.icon.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); @@ -450,6 +459,7 @@ public class VolumeDialogImpl implements VolumeDialog { private int computeTimeoutH() { if (mAccessibility.mFeedbackEnabled) return 20000; if (mHovering) return 16000; + if (mExpanded) return 5000; if (mSafetyWarning != null) return 5000; return 3000; } @@ -461,6 +471,8 @@ public class VolumeDialogImpl implements VolumeDialog { mDialogView.animate().cancel(); mShowing = false; + updateExpandedH(false /* expanding */, true /* dismissing */); + mDialogView.setTranslationY(0); mDialogView.setAlpha(1); mDialogView.animate() @@ -493,6 +505,76 @@ public class VolumeDialogImpl implements VolumeDialog { } } + private void updateExpandedH(final boolean expanded, final boolean dismissing) { + if (D.BUG) Log.d(TAG, "updateExpandedH " + expanded); + + if (mExpanded == expanded) return; + mExpanded = expanded; + mExpandButtonAnimationRunning = isAttached(); + updateExpandButtonH(); + TransitionManager.endTransitions(mDialogView); + final VolumeRow activeRow = getActiveRow(); + if (!dismissing) { + mWindow.setLayout(mWindow.getAttributes().width, ViewGroup.LayoutParams.MATCH_PARENT); + TransitionManager.beginDelayedTransition(mDialogView, getTransition()); + } + updateRowsH(activeRow); + rescheduleTimeoutH(); + } + + private AutoTransition getTransition() { + AutoTransition transition = new AutoTransition(); + transition.setDuration(300); + transition.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); + return transition; + } + + private void updateExpandButtonH() { + if (D.BUG) Log.d(TAG, "updateExpandButtonH"); + + mExpandButton.setClickable(!mExpandButtonAnimationRunning); + if (!(mExpandButtonAnimationRunning && isAttached())) { + final int res = mExpanded ? R.drawable.ic_volume_collapse_animation + : R.drawable.ic_volume_expand_animation; + if (hasTouchFeature()) { + mExpandButton.setImageResource(res); + } else { + // if there is no touch feature, show the volume ringer instead + mExpandButton.setImageResource(R.drawable.ic_volume_ringer); + mExpandButton.setBackgroundResource(0); // remove gray background emphasis + } + mExpandButton.setContentDescription(mContext.getString(mExpanded ? + R.string.accessibility_volume_collapse : R.string.accessibility_volume_expand)); + } + if (mExpandButtonAnimationRunning) { + final Drawable d = mExpandButton.getDrawable(); + if (d instanceof AnimatedVectorDrawable) { + // workaround to reset drawable + final AnimatedVectorDrawable avd = (AnimatedVectorDrawable) d.getConstantState() + .newDrawable(); + mExpandButton.setImageDrawable(avd); + avd.start(); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + mExpandButtonAnimationRunning = false; + updateExpandButtonH(); + rescheduleTimeoutH(); + } + }, 300); + } + } + } + + private boolean isAttached() { + return mDialogView != null && mDialogView.isAttachedToWindow(); + } + + private boolean hasTouchFeature() { + final PackageManager pm = mContext.getPackageManager(); + return pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN); + } + private boolean shouldBeVisibleH(VolumeRow row, VolumeRow activeRow) { boolean isActive = row == activeRow; if (row.stream == AudioSystem.STREAM_ACCESSIBILITY) { @@ -506,7 +588,7 @@ public class VolumeDialogImpl implements VolumeDialog { return true; } - return row.important || isActive; + return row.defaultStream || isActive || (mExpanded && row.important); } private void updateRowsH(final VolumeRow activeRow) { @@ -545,7 +627,7 @@ public class VolumeDialogImpl implements VolumeDialog { break; case AudioManager.RINGER_MODE_NORMAL: default: - boolean muted = (mAutomute && ss.level == 0) || ss.muted ? true : false; + boolean muted = (mAutomute && ss.level == 0) || ss.muted; if (muted) { mRingerStatus.setText(R.string.volume_ringer_status_silent); mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute); @@ -596,7 +678,7 @@ public class VolumeDialogImpl implements VolumeDialog { mDynamic.put(stream, true); if (findRow(stream) == null) { addRow(stream, R.drawable.ic_volume_remote, R.drawable.ic_volume_remote_mute, true, - true); + false, true); } } @@ -843,6 +925,16 @@ public class VolumeDialogImpl implements VolumeDialog { } } + private final OnClickListener mClickExpand = new OnClickListener() { + @Override + public void onClick(View v) { + mExpandButton.animate().cancel(); + final boolean newExpand = !mExpanded; + Events.writeEvent(mContext, Events.EVENT_EXPAND, newExpand); + updateExpandedH(newExpand, false /* dismissing */); + } + }; + private final VolumeDialogController.Callbacks mControllerCallbackH = new VolumeDialogController.Callbacks() { @Override @@ -898,8 +990,7 @@ public class VolumeDialogImpl implements VolumeDialog { @Override public void onAccessibilityModeChanged(Boolean showA11yStream) { - boolean show = showA11yStream == null ? false : showA11yStream; - mShowA11yStream = show; + mShowA11yStream = showA11yStream == null ? false : showA11yStream; VolumeRow activeRow = getActiveRow(); if (!mShowA11yStream && AudioManager.STREAM_ACCESSIBILITY == activeRow.stream) { dismissH(Events.DISMISS_STREAM_GONE); @@ -1100,6 +1191,7 @@ public class VolumeDialogImpl implements VolumeDialog { private int iconRes; private int iconMuteRes; private boolean important; + private boolean defaultStream; private ColorStateList cachedSliderTint; private int iconState; // from Events private ObjectAnimator anim; // slider progress animation for non-touch-related updates diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java index 1c104cffc3c1..3e6bd7e5bfe4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java @@ -28,6 +28,7 @@ class DozeHostFake implements DozeHost { Callback callback; boolean pulseExtended; boolean animateWakeup; + boolean animateScreenOff; boolean dozing; float doubleTapX; float doubleTapY; @@ -103,6 +104,11 @@ class DozeHostFake implements DozeHost { } @Override + public void setAnimateScreenOff(boolean animateScreenOff) { + this.animateScreenOff = animateScreenOff; + } + + @Override public void onDoubleTap(float x, float y) { doubleTapX = y; doubleTapY = y; diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java index 19a30cc3c2fd..75ade9d603e5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java @@ -16,6 +16,7 @@ package com.android.systemui.doze; +import static com.android.systemui.doze.DozeMachine.State.DOZE; import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD; import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSED; import static com.android.systemui.doze.DozeMachine.State.INITIALIZED; @@ -28,19 +29,20 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.app.AlarmManager; -import android.content.Context; import android.os.Handler; import android.os.HandlerThread; -import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.util.wakelock.WakeLockFake; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -66,8 +68,11 @@ public class DozeUiTest extends SysuiTestCase { mWakeLock = new WakeLockFake(); mHost = new DozeHostFake(); mHandler = mHandlerThread.getThreadHandler(); + DozeParameters params = mock(DozeParameters.class); + when(params.getCanControlScreenOffAnimation()).thenReturn(true); + when(params.getDisplayNeedsBlanking()).thenReturn(false); - mDozeUi = new DozeUi(mContext, mAlarmManager, mMachine, mWakeLock, mHost, mHandler); + mDozeUi = new DozeUi(mContext, mAlarmManager, mMachine, mWakeLock, mHost, mHandler, params); } @After @@ -89,4 +94,20 @@ public class DozeUiTest extends SysuiTestCase { verify(mAlarmManager).setExact(anyInt(), anyLong(), eq("doze_time_tick"), any(), any()); } + + @Test + public void propagatesAnimateScreenOff() { + Assert.assertTrue("animateScreenOff should be true", mHost.animateScreenOff); + + DozeParameters params = mock(DozeParameters.class); + new DozeUi(mContext, mAlarmManager, mMachine, mWakeLock, mHost, mHandler, params); + Assert.assertFalse("animateScreenOff should be false", mHost.animateScreenOff); + } + + @Test + public void transitionSetsAnimateWakeup() { + mHost.animateWakeup = false; + mDozeUi.transitionTo(UNINITIALIZED, DOZE); + Assert.assertTrue("animateScreenOff should be true", mHost.animateWakeup); + } }
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java index 58ff46ad54ee..544585a4a917 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java @@ -50,7 +50,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { @Test public void testGroupSummaryNotShowingIconWhenPublic() { mGroup.setSensitive(true, true); - mGroup.setHideSensitive(true, false, 0, 0); + mGroup.setHideSensitiveForIntrinsicHeight(true); Assert.assertTrue(mGroup.isSummaryWithChildren()); Assert.assertFalse(mGroup.isShowingIcon()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java index 6ecfe3e6be47..f562340664c8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java @@ -56,6 +56,7 @@ public class NotificationListenerTest extends SysuiTestCase { private NotificationListenerService.RankingMap mRanking; private Set<String> mKeysKeptForRemoteInput; private NotificationData mNotificationData; + private NotificationRemoteInputManager mRemoteInputManager; @Before public void setUp() { @@ -63,13 +64,14 @@ public class NotificationListenerTest extends SysuiTestCase { mPresenter = mock(NotificationPresenter.class); mNotificationData = mock(NotificationData.class); mRanking = mock(NotificationListenerService.RankingMap.class); + mRemoteInputManager = mock(NotificationRemoteInputManager.class); mKeysKeptForRemoteInput = new HashSet<>(); when(mPresenter.getHandler()).thenReturn(mHandler); when(mPresenter.getNotificationData()).thenReturn(mNotificationData); - when(mPresenter.getKeysKeptForRemoteInput()).thenReturn(mKeysKeptForRemoteInput); + when(mRemoteInputManager.getKeysKeptForRemoteInput()).thenReturn(mKeysKeptForRemoteInput); - mListener = new NotificationListener(mPresenter, mContext); + mListener = new NotificationListener(mPresenter, mRemoteInputManager, mContext); mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0, new Notification(), UserHandle.CURRENT, null, 0); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java new file mode 100644 index 000000000000..b881c098a1a3 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java @@ -0,0 +1,118 @@ +package com.android.systemui.statusbar; + +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.Notification; +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.os.UserHandle; +import android.service.notification.NotificationListenerService; +import android.service.notification.StatusBarNotification; +import android.support.test.filters.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import com.android.systemui.SysuiTestCase; + +import com.google.android.collect.Sets; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class NotificationRemoteInputManagerTest extends SysuiTestCase { + private static final String TEST_PACKAGE_NAME = "test"; + private static final int TEST_UID = 0; + + private Handler mHandler; + private TestableNotificationRemoteInputManager mRemoteInputManager; + private StatusBarNotification mSbn; + private NotificationData.Entry mEntry; + + @Mock private NotificationPresenter mPresenter; + @Mock private RemoteInputController.Delegate mDelegate; + @Mock private NotificationLockscreenUserManager mLockscreenUserManager; + @Mock private NotificationRemoteInputManager.Callback mCallback; + @Mock private RemoteInputController mController; + @Mock private NotificationListenerService.RankingMap mRanking; + @Mock private ExpandableNotificationRow mRow; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mHandler = new Handler(Looper.getMainLooper()); + + when(mPresenter.getHandler()).thenReturn(mHandler); + when(mPresenter.getLatestRankingMap()).thenReturn(mRanking); + + mRemoteInputManager = new TestableNotificationRemoteInputManager(mLockscreenUserManager, + mContext); + mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, + 0, new Notification(), UserHandle.CURRENT, null, 0); + mEntry = new NotificationData.Entry(mSbn); + mEntry.row = mRow; + + mRemoteInputManager.setUpWithPresenterForTest(mPresenter, mCallback, mDelegate, + mController); + } + + @Test + public void testOnRemoveNotificationNotKept() { + assertFalse(mRemoteInputManager.onRemoveNotification(mEntry)); + assertTrue(mRemoteInputManager.getRemoteInputEntriesToRemoveOnCollapse().isEmpty()); + } + + @Test + public void testOnRemoveNotificationKept() { + when(mController.isRemoteInputActive(mEntry)).thenReturn(true); + assertTrue(mRemoteInputManager.onRemoveNotification(mEntry)); + assertTrue(mRemoteInputManager.getRemoteInputEntriesToRemoveOnCollapse().equals( + Sets.newArraySet(mEntry))); + } + + @Test + public void testPerformOnRemoveNotification() { + when(mController.isRemoteInputActive(mEntry)).thenReturn(true); + mRemoteInputManager.getKeysKeptForRemoteInput().add(mEntry.key); + mRemoteInputManager.onPerformRemoveNotification(mSbn, mEntry); + + verify(mController).removeRemoteInput(mEntry, null); + assertTrue(mRemoteInputManager.getKeysKeptForRemoteInput().isEmpty()); + } + + @Test + public void testRemoveRemoteInputEntriesKeptUntilCollapsed() { + mRemoteInputManager.getRemoteInputEntriesToRemoveOnCollapse().add(mEntry); + mRemoteInputManager.removeRemoteInputEntriesKeptUntilCollapsed(); + + assertTrue(mRemoteInputManager.getRemoteInputEntriesToRemoveOnCollapse().isEmpty()); + verify(mController).removeRemoteInput(mEntry, null); + verify(mPresenter).removeNotification(mEntry.key, mRanking); + } + + private class TestableNotificationRemoteInputManager extends NotificationRemoteInputManager { + + public TestableNotificationRemoteInputManager( + NotificationLockscreenUserManager lockscreenUserManager, Context context) { + super(lockscreenUserManager, context); + } + + public void setUpWithPresenterForTest(NotificationPresenter presenter, + Callback callback, + RemoteInputController.Delegate delegate, + RemoteInputController controller) { + super.setUpWithPresenter(presenter, callback, delegate); + mRemoteInputController = controller; + } + } +} 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 b9f695be90cf..a40ef64b4a82 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 @@ -70,6 +70,7 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimVisibilityCallback = (Boolean visible) -> mScrimVisibile = visible; mDozeParamenters = mock(DozeParameters.class); when(mDozeParamenters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled); + when(mDozeParamenters.getDisplayNeedsBlanking()).thenReturn(true); mScrimController = new SynchronousScrimController(mLightBarController, mScrimBehind, mScrimInFront, mHeadsUpScrim, mScrimVisibilityCallback, mDozeParamenters); } @@ -229,6 +230,15 @@ public class ScrimControllerTest extends SysuiTestCase { verify(mWakeLock, times(1)).release(); } + @Test + public void testCallbackInvokedOnSameStateTransition() { + mScrimController.transitionTo(ScrimState.UNLOCKED); + mScrimController.finishAnimationsImmediately(); + ScrimController.Callback callback = mock(ScrimController.Callback.class); + mScrimController.transitionTo(ScrimState.UNLOCKED, callback); + verify(callback, times(1)).onFinished(); + } + private void assertScrimTint(ScrimView scrimView, boolean tinted) { final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT; final String name = scrimView == mScrimInFront ? "front" : "back"; 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 5ff90d91b333..e4c33f11221b 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 @@ -26,6 +26,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -107,6 +108,7 @@ public class StatusBarTest extends SysuiTestCase { ScrimController mScrimController; IStatusBarService mBarService; ArrayList<Entry> mNotificationList; + FingerprintUnlockController mFingerprintUnlockController; private DisplayMetrics mDisplayMetrics = new DisplayMetrics(); @Before @@ -133,6 +135,7 @@ public class StatusBarTest extends SysuiTestCase { when(mNotificationPanelView.getLayoutParams()).thenReturn(new LayoutParams(0, 0)); mNotificationList = mock(ArrayList.class); mScrimController = mock(ScrimController.class); + mFingerprintUnlockController = mock(FingerprintUnlockController.class); IPowerManager powerManagerService = mock(IPowerManager.class); HandlerThread handlerThread = new HandlerThread("TestThread"); handlerThread.start(); @@ -145,7 +148,7 @@ public class StatusBarTest extends SysuiTestCase { mStatusBar = new TestableStatusBar(mStatusBarKeyguardViewManager, mUnlockMethodCache, mKeyguardIndicationController, mStackScroller, mHeadsUpManager, mNotificationData, mPowerManager, mSystemServicesProxy, mNotificationPanelView, - mBarService, mScrimController); + mBarService, mScrimController, mFingerprintUnlockController); mStatusBar.mContext = mContext; mStatusBar.mComponents = mContext.getComponents(); doAnswer(invocation -> { @@ -538,18 +541,27 @@ public class StatusBarTest extends SysuiTestCase { @Test public void testFingerprintNotification_UpdatesScrims() { mStatusBar.mStatusBarWindowManager = mock(StatusBarWindowManager.class); - mStatusBar.mFingerprintUnlockController = mock(FingerprintUnlockController.class); mStatusBar.mDozeScrimController = mock(DozeScrimController.class); mStatusBar.notifyFpAuthModeChanged(); verify(mScrimController).transitionTo(any(), any()); } + @Test + public void testFingerprintUnlock_UpdatesScrims() { + // Simulate unlocking from AoD with fingerprint. + when(mFingerprintUnlockController.getMode()) + .thenReturn(FingerprintUnlockController.MODE_WAKE_AND_UNLOCK); + mStatusBar.updateScrimController(); + verify(mScrimController).transitionTo(eq(ScrimState.UNLOCKED), any()); + } + static class TestableStatusBar extends StatusBar { public TestableStatusBar(StatusBarKeyguardViewManager man, UnlockMethodCache unlock, KeyguardIndicationController key, NotificationStackScrollLayout stack, HeadsUpManager hum, NotificationData nd, PowerManager pm, SystemServicesProxy ssp, NotificationPanelView panelView, - IStatusBarService barService, ScrimController scrimController) { + IStatusBarService barService, ScrimController scrimController, + FingerprintUnlockController fingerprintUnlockController) { mStatusBarKeyguardViewManager = man; mUnlockMethodCache = unlock; mKeyguardIndicationController = key; @@ -563,6 +575,7 @@ public class StatusBarTest extends SysuiTestCase { mBarService = barService; mWakefulnessLifecycle = createAwakeWakefulnessLifecycle(); mScrimController = scrimController; + mFingerprintUnlockController = fingerprintUnlockController; } private WakefulnessLifecycle createAwakeWakefulnessLifecycle() { diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 7bc63f057f48..4bf3c5ab9268 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -26,6 +26,7 @@ import static com.android.server.autofill.Helper.sVerbose; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; +import android.app.ActivityManagerInternal; import android.app.AppGlobals; import android.app.IActivityManager; import android.content.ComponentName; @@ -42,6 +43,7 @@ import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.Looper; +import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; @@ -74,11 +76,11 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.os.HandlerCaller; +import com.android.server.LocalServices; import com.android.server.autofill.ui.AutoFillUI; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.Arrays; import java.util.Random; /** @@ -482,16 +484,17 @@ final class AutofillManagerServiceImpl { * Asserts the component is owned by the caller. */ private void assertCallerLocked(@NonNull ComponentName componentName) { + final String packageName = componentName.getPackageName(); final PackageManager pm = mContext.getPackageManager(); final int callingUid = Binder.getCallingUid(); final int packageUid; try { - packageUid = pm.getPackageUidAsUser(componentName.getPackageName(), - UserHandle.getCallingUserId()); + packageUid = pm.getPackageUidAsUser(packageName, UserHandle.getCallingUserId()); } catch (NameNotFoundException e) { throw new SecurityException("Could not verify UID for " + componentName); } - if (callingUid != packageUid) { + if (callingUid != packageUid && !LocalServices.getService(ActivityManagerInternal.class) + .hasRunningActivity(callingUid, packageName)) { final String[] packages = pm.getPackagesForUid(callingUid); final String callingPackage = packages != null ? packages[0] : "uid-" + callingUid; Slog.w(TAG, "App (package=" + callingPackage + ", UID=" + callingUid diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java index bd0d853ce698..1dba0529eaf4 100644 --- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java +++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java @@ -1520,7 +1520,11 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter } // clear an application's data, blocking until the operation completes or times out - public void clearApplicationDataSynchronous(String packageName) { + // if keepSystemState is true, we intentionally do not also clear system state that + // would ordinarily also be cleared, because we aren't actually wiping the app back + // to empty; we're bringing it into the actual expected state related to the already- + // restored notification state etc. + public void clearApplicationDataSynchronous(String packageName, boolean keepSystemState) { // Don't wipe packages marked allowClearUserData=false try { PackageInfo info = mPackageManager.getPackageInfo(packageName, 0); @@ -1541,7 +1545,7 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter synchronized (mClearDataLock) { mClearingData = true; try { - mActivityManager.clearApplicationUserData(packageName, observer, 0); + mActivityManager.clearApplicationUserData(packageName, keepSystemState, observer, 0); } catch (RemoteException e) { // can't happen because the activity manager is in this process } diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java index 888dcd7e7a5e..7efe5cadb5cc 100644 --- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java +++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java @@ -327,7 +327,7 @@ public class FullRestoreEngine extends RestoreEngine { Slog.d(TAG, "Clearing app data preparatory to full restore"); } - mBackupManagerService.clearApplicationDataSynchronous(pkg); + mBackupManagerService.clearApplicationDataSynchronous(pkg, true); } else { if (MORE_DEBUG) { Slog.d(TAG, "backup agent (" diff --git a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java index 22691bb60bfa..3dc242f1d48a 100644 --- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java +++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java @@ -591,7 +591,7 @@ public class PerformAdbRestoreTask implements Runnable { Slog.d(TAG, "Clearing app data preparatory to full restore"); } - mBackupManagerService.clearApplicationDataSynchronous(pkg); + mBackupManagerService.clearApplicationDataSynchronous(pkg, true); } else { if (DEBUG) { Slog.d(TAG, "backup agent (" diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java index 5884dc536080..2db743020237 100644 --- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java +++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java @@ -947,7 +947,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { // We also need to wipe the current target's data, as it's probably // in an incoherent state. backupManagerService.clearApplicationDataSynchronous( - mCurrentPackage.packageName); + mCurrentPackage.packageName, false); // Schedule the next state based on the nature of our failure if (status == BackupTransport.TRANSPORT_ERROR) { @@ -1115,7 +1115,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { // If the agent fails restore, it might have put the app's data // into an incoherent state. For consistency we wipe its data // again in this case before continuing with normal teardown - backupManagerService.clearApplicationDataSynchronous(mCurrentPackage.packageName); + backupManagerService.clearApplicationDataSynchronous(mCurrentPackage.packageName, false); keyValueAgentCleanup(); } diff --git a/services/core/java/com/android/server/AlarmManagerInternal.java b/services/core/java/com/android/server/AlarmManagerInternal.java new file mode 100644 index 000000000000..dbff957a0da7 --- /dev/null +++ b/services/core/java/com/android/server/AlarmManagerInternal.java @@ -0,0 +1,21 @@ +/* + * 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; + +public interface AlarmManagerInternal { + void removeAlarmsForUid(int uid); +} diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index ca1524959358..06cf9820ca5f 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -92,6 +92,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.DumpUtils; import com.android.internal.util.LocalLog; import com.android.server.ForceAppStandbyTracker.Listener; +import com.android.server.LocalServices; /** * Alarm manager implementaion. @@ -467,21 +468,14 @@ class AlarmManagerService extends SystemService { return newStart; } - boolean remove(final PendingIntent operation, final IAlarmListener listener) { - if (operation == null && listener == null) { - if (localLOGV) { - Slog.w(TAG, "requested remove() of null operation", - new RuntimeException("here")); - } - return false; - } + boolean remove(Predicate<Alarm> predicate) { boolean didRemove = false; long newStart = 0; // recalculate endpoints as we go long newEnd = Long.MAX_VALUE; int newFlags = 0; for (int i = 0; i < alarms.size(); ) { Alarm alarm = alarms.get(i); - if (alarm.matches(operation, listener)) { + if (predicate.test(alarm)) { alarms.remove(i); didRemove = true; if (alarm.alarmClock != null) { @@ -507,111 +501,6 @@ class AlarmManagerService extends SystemService { return didRemove; } - boolean remove(final String packageName) { - if (packageName == null) { - if (localLOGV) { - Slog.w(TAG, "requested remove() of null packageName", - new RuntimeException("here")); - } - return false; - } - boolean didRemove = false; - long newStart = 0; // recalculate endpoints as we go - long newEnd = Long.MAX_VALUE; - int newFlags = 0; - for (int i = alarms.size()-1; i >= 0; i--) { - Alarm alarm = alarms.get(i); - if (alarm.matches(packageName)) { - alarms.remove(i); - didRemove = true; - if (alarm.alarmClock != null) { - mNextAlarmClockMayChange = true; - } - } else { - if (alarm.whenElapsed > newStart) { - newStart = alarm.whenElapsed; - } - if (alarm.maxWhenElapsed < newEnd) { - newEnd = alarm.maxWhenElapsed; - } - newFlags |= alarm.flags; - } - } - if (didRemove) { - // commit the new batch bounds - start = newStart; - end = newEnd; - flags = newFlags; - } - return didRemove; - } - - boolean removeForStopped(final int uid) { - boolean didRemove = false; - long newStart = 0; // recalculate endpoints as we go - long newEnd = Long.MAX_VALUE; - int newFlags = 0; - for (int i = alarms.size()-1; i >= 0; i--) { - Alarm alarm = alarms.get(i); - try { - if (alarm.uid == uid && ActivityManager.getService().isAppStartModeDisabled( - uid, alarm.packageName)) { - alarms.remove(i); - didRemove = true; - if (alarm.alarmClock != null) { - mNextAlarmClockMayChange = true; - } - } else { - if (alarm.whenElapsed > newStart) { - newStart = alarm.whenElapsed; - } - if (alarm.maxWhenElapsed < newEnd) { - newEnd = alarm.maxWhenElapsed; - } - newFlags |= alarm.flags; - } - } catch (RemoteException e) { - } - } - if (didRemove) { - // commit the new batch bounds - start = newStart; - end = newEnd; - flags = newFlags; - } - return didRemove; - } - - boolean remove(final int userHandle) { - boolean didRemove = false; - long newStart = 0; // recalculate endpoints as we go - long newEnd = Long.MAX_VALUE; - for (int i = 0; i < alarms.size(); ) { - Alarm alarm = alarms.get(i); - if (UserHandle.getUserId(alarm.creatorUid) == userHandle) { - alarms.remove(i); - didRemove = true; - if (alarm.alarmClock != null) { - mNextAlarmClockMayChange = true; - } - } else { - if (alarm.whenElapsed > newStart) { - newStart = alarm.whenElapsed; - } - if (alarm.maxWhenElapsed < newEnd) { - newEnd = alarm.maxWhenElapsed; - } - i++; - } - } - if (didRemove) { - // commit the new batch bounds - start = newStart; - end = newEnd; - } - return didRemove; - } - boolean hasPackage(final String packageName) { final int N = alarms.size(); for (int i = 0; i < N; i++) { @@ -759,6 +648,8 @@ class AlarmManagerService extends SystemService { mForceAppStandbyTracker = ForceAppStandbyTracker.getInstance(context); mForceAppStandbyTracker.addListener(mForceAppStandbyListener); + + publishLocalService(AlarmManagerInternal.class, new LocalService()); } static long convertToElapsed(long when, int type) { @@ -1554,6 +1445,21 @@ class AlarmManagerService extends SystemService { } } + /** + * System-process internal API + */ + private final class LocalService implements AlarmManagerInternal { + @Override + public void removeAlarmsForUid(int uid) { + synchronized (mLock) { + removeLocked(uid); + } + } + } + + /** + * Public-facing binder interface + */ private final IBinder mService = new IAlarmManager.Stub() { @Override public void set(String callingPackage, @@ -2430,10 +2336,19 @@ class AlarmManagerService extends SystemService { } private void removeLocked(PendingIntent operation, IAlarmListener directReceiver) { + if (operation == null && directReceiver == null) { + if (localLOGV) { + Slog.w(TAG, "requested remove() of null operation", + new RuntimeException("here")); + } + return; + } + boolean didRemove = false; + final Predicate<Alarm> whichAlarms = (Alarm a) -> a.matches(operation, directReceiver); for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { Batch b = mAlarmBatches.get(i); - didRemove |= b.remove(operation, directReceiver); + didRemove |= b.remove(whichAlarms); if (b.size() == 0) { mAlarmBatches.remove(i); } @@ -2476,11 +2391,58 @@ class AlarmManagerService extends SystemService { } } - void removeLocked(String packageName) { + void removeLocked(final int uid) { boolean didRemove = false; + final Predicate<Alarm> whichAlarms = (Alarm a) -> a.uid == uid; for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { Batch b = mAlarmBatches.get(i); - didRemove |= b.remove(packageName); + didRemove |= b.remove(whichAlarms); + if (b.size() == 0) { + mAlarmBatches.remove(i); + } + } + for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) { + final Alarm a = mPendingWhileIdleAlarms.get(i); + if (a.uid == uid) { + // Don't set didRemove, since this doesn't impact the scheduled alarms. + mPendingWhileIdleAlarms.remove(i); + } + } + for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i --) { + final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i); + for (int j = alarmsForUid.size() - 1; j >= 0; j--) { + if (alarmsForUid.get(j).uid == uid) { + alarmsForUid.remove(j); + } + } + if (alarmsForUid.size() == 0) { + mPendingBackgroundAlarms.removeAt(i); + } + } + if (didRemove) { + if (DEBUG_BATCH) { + Slog.v(TAG, "remove(uid) changed bounds; rebatching"); + } + rebatchAllAlarmsLocked(true); + rescheduleKernelAlarmsLocked(); + updateNextAlarmClockLocked(); + } + } + + void removeLocked(final String packageName) { + if (packageName == null) { + if (localLOGV) { + Slog.w(TAG, "requested remove() of null packageName", + new RuntimeException("here")); + } + return; + } + + boolean didRemove = false; + final Predicate<Alarm> whichAlarms = (Alarm a) -> a.matches(packageName); + for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { + Batch b = mAlarmBatches.get(i); + didRemove |= b.remove(whichAlarms); if (b.size() == 0) { mAlarmBatches.remove(i); } @@ -2513,11 +2475,20 @@ class AlarmManagerService extends SystemService { } } - void removeForStoppedLocked(int uid) { + void removeForStoppedLocked(final int uid) { boolean didRemove = false; + final Predicate<Alarm> whichAlarms = (Alarm a) -> { + try { + if (a.uid == uid && ActivityManager.getService().isAppStartModeDisabled( + uid, a.packageName)) { + return true; + } + } catch (RemoteException e) { /* fall through */} + return false; + }; for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { Batch b = mAlarmBatches.get(i); - didRemove |= b.removeForStopped(uid); + didRemove |= b.remove(whichAlarms); if (b.size() == 0) { mAlarmBatches.remove(i); } @@ -2546,9 +2517,11 @@ class AlarmManagerService extends SystemService { void removeUserLocked(int userHandle) { boolean didRemove = false; + final Predicate<Alarm> whichAlarms = + (Alarm a) -> UserHandle.getUserId(a.creatorUid) == userHandle; for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { Batch b = mAlarmBatches.get(i); - didRemove |= b.remove(userHandle); + didRemove |= b.remove(whichAlarms); if (b.size() == 0) { mAlarmBatches.remove(i); } @@ -2967,7 +2940,7 @@ class AlarmManagerService extends SystemService { proto.write(AlarmProto.TAG, statsTag); proto.write(AlarmProto.TYPE, type); - proto.write(AlarmProto.WHEN_ELAPSED_MS, whenElapsed - nowElapsed); + proto.write(AlarmProto.TIME_UNTIL_WHEN_ELAPSED_MS, whenElapsed - nowElapsed); proto.write(AlarmProto.WINDOW_LENGTH_MS, windowLength); proto.write(AlarmProto.REPEAT_INTERVAL_MS, repeatInterval); proto.write(AlarmProto.COUNT, count); @@ -3396,6 +3369,7 @@ class AlarmManagerService extends SystemService { @Override public void onReceive(Context context, Intent intent) { + final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); synchronized (mLock) { String action = intent.getAction(); String pkgList[] = null; @@ -3416,7 +3390,6 @@ class AlarmManagerService extends SystemService { removeUserLocked(userHandle); } } else if (Intent.ACTION_UID_REMOVED.equals(action)) { - int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); if (uid >= 0) { mLastAllowWhileIdleDispatch.delete(uid); } @@ -3436,7 +3409,13 @@ class AlarmManagerService extends SystemService { } if (pkgList != null && (pkgList.length > 0)) { for (String pkg : pkgList) { - removeLocked(pkg); + if (uid >= 0) { + // package-removed case + removeLocked(uid); + } else { + // external-applications-unavailable etc case + removeLocked(pkg); + } mPriorities.remove(pkg); for (int i=mBroadcastStats.size()-1; i>=0; i--) { ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i); diff --git a/services/core/java/com/android/server/GraphicsStatsService.java b/services/core/java/com/android/server/GraphicsStatsService.java index d3f77b64bc2f..4639d7586f83 100644 --- a/services/core/java/com/android/server/GraphicsStatsService.java +++ b/services/core/java/com/android/server/GraphicsStatsService.java @@ -175,7 +175,8 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { 0, UserHandle.getUserId(uid)); synchronized (mLock) { - pfd = requestBufferForProcessLocked(token, uid, pid, packageName, info.versionCode); + pfd = requestBufferForProcessLocked(token, uid, pid, packageName, + info.getLongVersionCode()); } } catch (PackageManager.NameNotFoundException ex) { throw new RemoteException("Unable to find package: '" + packageName + "'"); @@ -197,7 +198,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { } private ParcelFileDescriptor requestBufferForProcessLocked(IGraphicsStatsCallback token, - int uid, int pid, String packageName, int versionCode) throws RemoteException { + int uid, int pid, String packageName, long versionCode) throws RemoteException { ActiveBuffer buffer = fetchActiveBuffersLocked(token, uid, pid, packageName, versionCode); scheduleRotateLocked(); return getPfd(buffer.mProcessBuffer); @@ -292,7 +293,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { } private ActiveBuffer fetchActiveBuffersLocked(IGraphicsStatsCallback token, int uid, int pid, - String packageName, int versionCode) throws RemoteException { + String packageName, long versionCode) throws RemoteException { int size = mActive.size(); long today = normalizeDate(System.currentTimeMillis()).getTimeInMillis(); for (int i = 0; i < size; i++) { @@ -381,19 +382,19 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { private static native int nGetAshmemSize(); private static native long nCreateDump(int outFd, boolean isProto); private static native void nAddToDump(long dump, String path, String packageName, - int versionCode, long startTime, long endTime, byte[] data); + long versionCode, long startTime, long endTime, byte[] data); private static native void nAddToDump(long dump, String path); private static native void nFinishDump(long dump); - private static native void nSaveBuffer(String path, String packageName, int versionCode, + private static native void nSaveBuffer(String path, String packageName, long versionCode, long startTime, long endTime, byte[] data); private final class BufferInfo { final String packageName; - final int versionCode; + final long versionCode; long startTime; long endTime; - BufferInfo(String packageName, int versionCode, long startTime) { + BufferInfo(String packageName, long versionCode, long startTime) { this.packageName = packageName; this.versionCode = versionCode; this.startTime = startTime; @@ -408,7 +409,8 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { final IBinder mToken; MemoryFile mProcessBuffer; - ActiveBuffer(IGraphicsStatsCallback token, int uid, int pid, String packageName, int versionCode) + ActiveBuffer(IGraphicsStatsCallback token, int uid, int pid, String packageName, + long versionCode) throws RemoteException, IOException { mInfo = new BufferInfo(packageName, versionCode, System.currentTimeMillis()); mUid = uid; diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index dc35051d2dfe..5fed93b1b0b1 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -49,12 +49,14 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; +import android.Manifest; import android.annotation.BinderThread; import android.annotation.ColorInt; import android.annotation.IntDef; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManagerInternal; @@ -104,6 +106,8 @@ import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; +import android.os.ShellCallback; +import android.os.ShellCommand; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; @@ -178,6 +182,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub static final boolean DEBUG_RESTORE = DEBUG || false; static final String TAG = "InputMethodManagerService"; + @Retention(SOURCE) + @IntDef({ShellCommandResult.SUCCESS, ShellCommandResult.FAILURE}) + private @interface ShellCommandResult { + int SUCCESS = 0; + int FAILURE = -1; + } + static final int MSG_SHOW_IM_SUBTYPE_PICKER = 1; static final int MSG_SHOW_IM_SUBTYPE_ENABLER = 2; static final int MSG_SHOW_IM_CONFIG = 3; @@ -889,7 +900,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub /** * Start a VR InputMethod that matches IME with package name of {@param component}. - * Note: This method is called from {@link VrManager}. + * Note: This method is called from {@link android.app.VrManager}. */ private void startVrInputMethodNoCheck(@Nullable ComponentName component) { if (component == null) { @@ -903,7 +914,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub for (InputMethodInfo info : mMethodList) { if (TextUtils.equals(info.getPackageName(), packageName) && info.isVrOnly()) { // set this is as current inputMethod without updating settings. - setInputMethodEnabled(info.getId(), true); + setInputMethodEnabledLocked(info.getId(), true); setInputMethodLocked(info.getId(), NOT_A_SUBTYPE_ID); break; } @@ -3885,30 +3896,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // ---------------------------------------------------------------------- - @Override - public boolean setInputMethodEnabled(String id, boolean enabled) { - // TODO: Make this work even for non-current users? - if (!calledFromValidUser()) { - return false; - } - synchronized (mMethodMap) { - if (mContext.checkCallingOrSelfPermission( - android.Manifest.permission.WRITE_SECURE_SETTINGS) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException( - "Requires permission " - + android.Manifest.permission.WRITE_SECURE_SETTINGS); - } - - long ident = Binder.clearCallingIdentity(); - try { - return setInputMethodEnabledLocked(id, enabled); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - } - boolean setInputMethodEnabledLocked(String id, boolean enabled) { // Make sure this is a valid input method. InputMethodInfo imm = mMethodMap.get(id); @@ -4633,4 +4620,257 @@ public class InputMethodManagerService extends IInputMethodManager.Stub p.println("No input method service."); } } + + @BinderThread + @Override + public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out, + @Nullable FileDescriptor err, + @NonNull String[] args, @Nullable ShellCallback callback, + @NonNull ResultReceiver resultReceiver) throws RemoteException { + new ShellCommandImpl(this).exec( + this, in, out, err, args, callback, resultReceiver); + } + + private static final class ShellCommandImpl extends ShellCommand { + @NonNull + final InputMethodManagerService mService; + + ShellCommandImpl(InputMethodManagerService service) { + mService = service; + } + + @BinderThread + @ShellCommandResult + @Override + public int onCommand(@Nullable String cmd) { + if (cmd == null) { + return handleDefaultCommands(cmd); + } + switch (cmd) { + case "list": + return mService.handleShellCommandListInputMethods(this); + case "enable": + return mService.handleShellCommandEnableDisableInputMethod(this, true); + case "disable": + return mService.handleShellCommandEnableDisableInputMethod(this, false); + case "set": + return mService.handleShellCommandSetInputMethod(this); + case "reset-ime": + return mService.handleShellCommandResetInputMethod(this); + default: + return handleDefaultCommands(cmd); + } + } + + @BinderThread + @Override + public void onHelp() { + try (PrintWriter pw = getOutPrintWriter()) { + pw.println("InputMethodManagerService commands:"); + pw.println(" help"); + pw.println(" Prints this help text."); + pw.println(" dump [options]"); + pw.println(" Synonym of dumpsys."); + pw.println(" list [-a] [-s]"); + pw.println(" prints all enabled input methods."); + pw.println(" -a: see all input methods"); + pw.println(" -s: only a single summary line of each"); + pw.println(" enable <ID>"); + pw.println(" allows the given input method ID to be used."); + pw.println(" disable <ID>"); + pw.println(" disallows the given input method ID to be used."); + pw.println(" set <ID>"); + pw.println(" switches to the given input method ID."); + pw.println(" reset-ime"); + pw.println(" reset currently selected/enabled IMEs to the default ones as if"); + pw.println(" the device is initially booted with the current locale."); + } + } + } + + // ---------------------------------------------------------------------- + // Shell command handlers: + + /** + * Handles {@code adb shell ime list}. + * @param shellCommand {@link ShellCommand} object that is handling this command. + * @return Exit code of the command. + */ + @BinderThread + @ShellCommandResult + private int handleShellCommandListInputMethods(@NonNull ShellCommand shellCommand) { + boolean all = false; + boolean brief = false; + while (true) { + final String nextOption = shellCommand.getNextOption(); + if (nextOption == null) { + break; + } + switch (nextOption) { + case "-a": + all = true; + break; + case "-s": + brief = true; + break; + } + } + final List<InputMethodInfo> methods = all ? + getInputMethodList() : getEnabledInputMethodList(); + final PrintWriter pr = shellCommand.getOutPrintWriter(); + final Printer printer = x -> pr.println(x); + final int N = methods.size(); + for (int i = 0; i < N; ++i) { + if (brief) { + pr.println(methods.get(i).getId()); + } else { + pr.print(methods.get(i).getId()); pr.println(":"); + methods.get(i).dump(printer, " "); + } + } + return ShellCommandResult.SUCCESS; + } + + /** + * Handles {@code adb shell ime enable} and {@code adb shell ime disable}. + * @param shellCommand {@link ShellCommand} object that is handling this command. + * @param enabled {@code true} if the command was {@code adb shell ime enable}. + * @return Exit code of the command. + */ + @BinderThread + @ShellCommandResult + @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) + private int handleShellCommandEnableDisableInputMethod( + @NonNull ShellCommand shellCommand, boolean enabled) { + if (!calledFromValidUser()) { + shellCommand.getErrPrintWriter().print( + "Must be called from the foreground user or with INTERACT_ACROSS_USERS_FULL"); + return ShellCommandResult.FAILURE; + } + final String id = shellCommand.getNextArgRequired(); + + final boolean previouslyEnabled; + synchronized (mMethodMap) { + if (mContext.checkCallingOrSelfPermission( + android.Manifest.permission.WRITE_SECURE_SETTINGS) + != PackageManager.PERMISSION_GRANTED) { + shellCommand.getErrPrintWriter().print( + "Caller must have WRITE_SECURE_SETTINGS permission"); + throw new SecurityException( + "Requires permission " + + android.Manifest.permission.WRITE_SECURE_SETTINGS); + } + + final long ident = Binder.clearCallingIdentity(); + try { + previouslyEnabled = setInputMethodEnabledLocked(id, enabled); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + final PrintWriter pr = shellCommand.getOutPrintWriter(); + pr.print("Input method "); + pr.print(id); + pr.print(": "); + pr.print((enabled == previouslyEnabled) ? "already " : "now "); + pr.println(enabled ? "enabled" : "disabled"); + return ShellCommandResult.SUCCESS; + } + + /** + * Handles {@code adb shell ime set}. + * @param shellCommand {@link ShellCommand} object that is handling this command. + * @return Exit code of the command. + */ + @BinderThread + @ShellCommandResult + private int handleShellCommandSetInputMethod(@NonNull ShellCommand shellCommand) { + final String id = shellCommand.getNextArgRequired(); + setInputMethod(null, id); + final PrintWriter pr = shellCommand.getOutPrintWriter(); + pr.print("Input method "); + pr.print(id); + pr.println(" selected"); + return ShellCommandResult.SUCCESS; + } + + /** + * Handles {@code adb shell ime reset-ime}. + * @param shellCommand {@link ShellCommand} object that is handling this command. + * @return Exit code of the command. + */ + @BinderThread + @ShellCommandResult + @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) + private int handleShellCommandResetInputMethod(@NonNull ShellCommand shellCommand) { + if (!calledFromValidUser()) { + shellCommand.getErrPrintWriter().print( + "Must be called from the foreground user or with INTERACT_ACROSS_USERS_FULL"); + return ShellCommandResult.FAILURE; + } + synchronized (mMethodMap) { + if (mContext.checkCallingOrSelfPermission( + android.Manifest.permission.WRITE_SECURE_SETTINGS) + != PackageManager.PERMISSION_GRANTED) { + shellCommand.getErrPrintWriter().print( + "Caller must have WRITE_SECURE_SETTINGS permission"); + throw new SecurityException( + "Requires permission " + + android.Manifest.permission.WRITE_SECURE_SETTINGS); + } + final String nextIme; + final List<InputMethodInfo> nextEnabledImes; + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mMethodMap) { + hideCurrentInputLocked(0, null); + unbindCurrentMethodLocked(false); + // Reset the current IME + resetSelectedInputMethodAndSubtypeLocked(null); + // Also reset the settings of the current IME + mSettings.putSelectedInputMethod(null); + // Disable all enabled IMEs. + { + final ArrayList<InputMethodInfo> enabledImes = + mSettings.getEnabledInputMethodListLocked(); + final int N = enabledImes.size(); + for (int i = 0; i < N; ++i) { + setInputMethodEnabledLocked(enabledImes.get(i).getId(), false); + } + } + // Re-enable with default enabled IMEs. + { + final ArrayList<InputMethodInfo> defaultEnabledIme = + InputMethodUtils.getDefaultEnabledImes(mContext, mMethodList); + final int N = defaultEnabledIme.size(); + for (int i = 0; i < N; ++i) { + setInputMethodEnabledLocked(defaultEnabledIme.get(i).getId(), true); + } + } + updateInputMethodsFromSettingsLocked(true /* enabledMayChange */); + InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mIPackageManager, + mSettings.getEnabledInputMethodListLocked(), + mSettings.getCurrentUserId(), + mContext.getBasePackageName()); + nextIme = mSettings.getSelectedInputMethod(); + nextEnabledImes = getEnabledInputMethodList(); + } + } finally { + Binder.restoreCallingIdentity(ident); + } + final PrintWriter pr = shellCommand.getOutPrintWriter(); + pr.println("Reset current and enabled IMEs"); + pr.println("Newly selected IME:"); + pr.print(" "); pr.println(nextIme); + pr.println("Newly enabled IMEs:"); + { + final int N = nextEnabledImes.size(); + for (int i = 0; i < N; ++i) { + pr.print(" "); + pr.println(nextEnabledImes.get(i).getId()); + } + } + return ShellCommandResult.SUCCESS; + } + } } diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 0d4f5cb81b49..0ffc77923f1a 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -2118,13 +2118,14 @@ public class AccountManagerService userId)); } /* - * Only the system or authenticator should be allowed to remove accounts for that - * authenticator. This will let users remove accounts (via Settings in the system) but not - * arbitrary applications (like competing authenticators). + * Only the system, authenticator or profile owner should be allowed to remove accounts for + * that authenticator. This will let users remove accounts (via Settings in the system) but + * not arbitrary applications (like competing authenticators). */ UserHandle user = UserHandle.of(userId); if (!isAccountManagedByCaller(account.type, callingUid, user.getIdentifier()) - && !isSystemUid(callingUid)) { + && !isSystemUid(callingUid) + && !isProfileOwner(callingUid)) { String msg = String.format( "uid %s cannot remove accounts of type: %s", callingUid, diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 5d6cf749bd1c..6760c862dbb6 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -401,6 +401,7 @@ import com.android.internal.util.FastPrintWriter; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.MemInfoReader; import com.android.internal.util.Preconditions; +import com.android.server.AlarmManagerInternal; import com.android.server.AppOpsService; import com.android.server.AttributeCache; import com.android.server.DeviceIdleController; @@ -471,6 +472,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import dalvik.system.VMRuntime; + import libcore.io.IoUtils; import libcore.util.EmptyArray; @@ -5948,7 +5950,7 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public boolean clearApplicationUserData(final String packageName, + public boolean clearApplicationUserData(final String packageName, boolean keepState, final IPackageDataObserver observer, int userId) { enforceNotIsolatedCaller("clearApplicationUserData"); int uid = Binder.getCallingUid(); @@ -6052,14 +6054,27 @@ public class ActivityManagerService extends IActivityManager.Stub pm.clearApplicationUserData(packageName, localObserver, resolvedUserId); if (appInfo != null) { - synchronized (this) { - // Remove all permissions granted from/to this package - removeUriPermissionsForPackageLocked(packageName, resolvedUserId, true); + // Restore already established notification state and permission grants, + // so it told us to keep those intact -- it's about to emplace app data + // that is appropriate for those bits of system state. + if (!keepState) { + synchronized (this) { + // Remove all permissions granted from/to this package + removeUriPermissionsForPackageLocked(packageName, resolvedUserId, true); + } + + // Reset notification state + INotificationManager inm = NotificationManager.getService(); + inm.clearData(packageName, appInfo.uid, uid == appInfo.uid); } - // Reset notification settings. - INotificationManager inm = NotificationManager.getService(); - inm.clearData(packageName, appInfo.uid, uid == appInfo.uid); + // Clear its scheduled jobs + JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class); + js.cancelJobsForUid(appInfo.uid, "clear data"); + + // Clear its pending alarms + AlarmManagerInternal ami = LocalServices.getService(AlarmManagerInternal.class); + ami.removeAlarmsForUid(uid); } } catch (RemoteException e) { } @@ -24478,6 +24493,26 @@ public class ActivityManagerService extends IActivityManager.Stub public boolean isRuntimeRestarted() { return mSystemServiceManager.isRuntimeRestarted(); } + + @Override + public boolean hasRunningActivity(int uid, @Nullable String packageName) { + if (packageName == null) return false; + + synchronized (ActivityManagerService.this) { + for (int i = 0; i < mLruProcesses.size(); i++) { + final ProcessRecord processRecord = mLruProcesses.get(i); + if (processRecord.uid == uid) { + for (int j = 0; j < processRecord.activities.size(); j++) { + final ActivityRecord activityRecord = processRecord.activities.get(j); + if (packageName.equals(activityRecord.packageName)) { + return true; + } + } + } + } + } + return false; + } } /** diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 979323fc8408..54938eb05cf5 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -69,7 +69,9 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import static android.app.ActivityManager.RESIZE_MODE_SYSTEM; import static android.app.ActivityManager.RESIZE_MODE_USER; @@ -1867,10 +1869,24 @@ final class ActivityManagerShellCommand extends ShellCommand { String value = getNextArgRequired(); int bucket = bucketNameToBucketValue(value); if (bucket < 0) return -1; + boolean multiple = peekNextArg() != null; + IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService( Context.USAGE_STATS_SERVICE)); - usm.setAppStandbyBucket(packageName, bucketNameToBucketValue(value), userId); + if (!multiple) { + usm.setAppStandbyBucket(packageName, bucketNameToBucketValue(value), userId); + } else { + HashMap<String, Integer> buckets = new HashMap<>(); + buckets.put(packageName, bucket); + while ((packageName = getNextArg()) != null) { + value = getNextArgRequired(); + bucket = bucketNameToBucketValue(value); + if (bucket < 0) continue; + buckets.put(packageName, bucket); + } + usm.setAppStandbyBuckets(buckets, userId); + } return 0; } @@ -1886,12 +1902,21 @@ final class ActivityManagerShellCommand extends ShellCommand { return -1; } } - String packageName = getNextArgRequired(); + String packageName = getNextArg(); IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService( Context.USAGE_STATS_SERVICE)); - int bucket = usm.getAppStandbyBucket(packageName, null, userId); - pw.println(bucket); + if (packageName != null) { + int bucket = usm.getAppStandbyBucket(packageName, null, userId); + pw.println(bucket); + } else { + Map<String, Integer> buckets = (Map<String, Integer>) usm.getAppStandbyBuckets( + SHELL_PACKAGE_NAME, userId); + for (Map.Entry<String, Integer> entry: buckets.entrySet()) { + pw.print(entry.getKey()); pw.print(": "); + pw.println(entry.getValue()); + } + } 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 87690d1961a9..93fb3e3e3e6e 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -1335,8 +1335,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub null, mStats.mHandler, null, mUserManagerUserInfoProvider); checkinStats.readSummaryFromParcel(in); in.recycle(); - checkinStats.dumpProtoLocked(mContext, fd, apps, flags, - historyStart); + checkinStats.dumpProtoLocked(mContext, fd, apps, flags); mStats.mCheckinFile.delete(); return; } @@ -1349,7 +1348,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub } if (DBG) Slog.d(TAG, "begin dumpProtoLocked from UID " + Binder.getCallingUid()); synchronized (mStats) { - mStats.dumpProtoLocked(mContext, fd, apps, flags, historyStart); + mStats.dumpProtoLocked(mContext, fd, apps, flags); if (writeData) { mStats.writeAsyncLocked(); } diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 48737a54cadc..dabcbcdcbb7c 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -2376,8 +2376,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi activities.add(activity); } } else { - Slog.e(TAG, "restoreTask: Unexpected name=" + name); - XmlUtils.skipCurrentTag(in); + handleUnknownTag(name, in); } } } @@ -2441,5 +2440,11 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task); return task; } + + void handleUnknownTag(String name, XmlPullParser in) + throws IOException, XmlPullParserException { + Slog.e(TAG, "restoreTask: Unexpected name=" + name); + XmlUtils.skipCurrentTag(in); + } } } diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 6bd599bb0198..14260c5fb105 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -926,10 +926,9 @@ class UserController implements Handler.Callback { final Integer userIdInt = userId; mUserLru.remove(userIdInt); mUserLru.add(userIdInt); - - if (unlockListener != null) { - uss.mUnlockProgress.addListener(unlockListener); - } + } + if (unlockListener != null) { + uss.mUnlockProgress.addListener(unlockListener); } if (updateUmState) { mInjector.getUserManagerInternal().setUserState(userId, uss.state); diff --git a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java index 28c358582dbe..bd2e96ed4ef2 100644 --- a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java +++ b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java @@ -51,6 +51,7 @@ public class DefaultNetworkMetrics { // Information about the current status of the default network. @GuardedBy("this") private DefaultNetworkEvent mCurrentDefaultNetwork; + // True if the current default network has been validated. @GuardedBy("this") private boolean mIsCurrentlyValid; @GuardedBy("this") @@ -71,6 +72,8 @@ public class DefaultNetworkMetrics { printEvent(localTimeMs, pw, ev); } mCurrentDefaultNetwork.updateDuration(timeMs); + // When printing default network events for bug reports, update validation time + // and refresh the last validation timestmap for future validation time updates. if (mIsCurrentlyValid) { updateValidationTime(timeMs); mLastValidationTimeMs = timeMs; @@ -92,11 +95,13 @@ public class DefaultNetworkMetrics { } public synchronized void logDefaultNetworkValidity(long timeMs, boolean isValid) { + // Transition from valid to invalid: update validity duration since last update if (!isValid && mIsCurrentlyValid) { mIsCurrentlyValid = false; updateValidationTime(timeMs); } + // Transition from invalid to valid: simply mark the validation timestamp. if (isValid && !mIsCurrentlyValid) { mIsCurrentlyValid = true; mLastValidationTimeMs = timeMs; @@ -114,6 +119,9 @@ public class DefaultNetworkMetrics { } private void logCurrentDefaultNetwork(long timeMs, NetworkAgentInfo oldNai) { + if (mIsCurrentlyValid) { + updateValidationTime(timeMs); + } DefaultNetworkEvent ev = mCurrentDefaultNetwork; ev.updateDuration(timeMs); ev.previousTransports = mLastTransports; @@ -122,7 +130,6 @@ public class DefaultNetworkMetrics { // The system acquired a new default network. fillLinkInfo(ev, oldNai); ev.finalScore = oldNai.getCurrentScore(); - ev.validatedMs = ev.durationMs; } // Only change transport of the previous default network if the event currently logged // corresponds to an existing default network, and not to the absence of a default network. @@ -143,9 +150,10 @@ public class DefaultNetworkMetrics { fillLinkInfo(ev, newNai); ev.initialScore = newNai.getCurrentScore(); if (newNai.lastValidated) { - mIsCurrentlyValid = true; - mLastValidationTimeMs = timeMs; + logDefaultNetworkValidity(timeMs, true); } + } else { + mIsCurrentlyValid = false; } mCurrentDefaultNetwork = ev; } diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index c4e6ff6bc906..6280edb87a02 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -644,6 +644,11 @@ public final class ContentService extends IContentService.Stub { int userId = UserHandle.getCallingUserId(); final int callingUid = Binder.getCallingUid(); + if (request.isPeriodic()) { + mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, + "no permission to write the sync settings"); + } + long identityToken = clearCallingIdentity(); try { SyncStorageEngine.EndPoint info; @@ -653,8 +658,6 @@ public final class ContentService extends IContentService.Stub { info = new SyncStorageEngine.EndPoint(account, provider, userId); if (request.isPeriodic()) { // Remove periodic sync. - mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, - "no permission to write the sync settings"); getSyncManager().removePeriodicSync(info, extras, "cancelRequest() by uid=" + callingUid); } diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index bdfd4bdab3b9..965159bdfd76 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -565,7 +565,7 @@ public class SyncManager { mLogger = SyncLogger.getInstance(); - SyncStorageEngine.init(context); + SyncStorageEngine.init(context, BackgroundThread.get().getLooper()); mSyncStorageEngine = SyncStorageEngine.getSingleton(); mSyncStorageEngine.setOnSyncRequestListener(new OnSyncRequestListener() { @Override @@ -735,15 +735,15 @@ public class SyncManager { } public void onStartUser(int userHandle) { - mLogger.log("onStartUser: user=", userHandle); + mSyncHandler.post(() -> mLogger.log("onStartUser: user=", userHandle)); } public void onUnlockUser(int userHandle) { - mLogger.log("onUnlockUser: user=", userHandle); + mSyncHandler.post(() -> mLogger.log("onUnlockUser: user=", userHandle)); } public void onStopUser(int userHandle) { - mLogger.log("onStopUser: user=", userHandle); + mSyncHandler.post(() -> mLogger.log("onStopUser: user=", userHandle)); } diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java index 3591871f5386..e498666073ed 100644 --- a/services/core/java/com/android/server/content/SyncStorageEngine.java +++ b/services/core/java/com/android/server/content/SyncStorageEngine.java @@ -36,6 +36,7 @@ import android.database.sqlite.SQLiteQueryBuilder; import android.os.Bundle; import android.os.Environment; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.RemoteCallbackList; @@ -69,7 +70,7 @@ import java.util.TimeZone; * * @hide */ -public class SyncStorageEngine extends Handler { +public class SyncStorageEngine { private static final String TAG = "SyncManager"; private static final String TAG_FILE = "SyncManagerFile"; @@ -462,7 +463,10 @@ public class SyncStorageEngine extends Handler { private boolean mGrantSyncAdaptersAccountAccess; - private SyncStorageEngine(Context context, File dataDir) { + private final MyHandler mHandler; + + private SyncStorageEngine(Context context, File dataDir, Looper looper) { + mHandler = new MyHandler(looper); mContext = context; sSyncStorageEngine = this; @@ -491,15 +495,15 @@ public class SyncStorageEngine extends Handler { } public static SyncStorageEngine newTestInstance(Context context) { - return new SyncStorageEngine(context, context.getFilesDir()); + return new SyncStorageEngine(context, context.getFilesDir(), Looper.getMainLooper()); } - public static void init(Context context) { + public static void init(Context context, Looper looper) { if (sSyncStorageEngine != null) { return; } File dataDir = Environment.getDataDirectory(); - sSyncStorageEngine = new SyncStorageEngine(context, dataDir); + sSyncStorageEngine = new SyncStorageEngine(context, dataDir, looper); } public static SyncStorageEngine getSingleton() { @@ -527,14 +531,21 @@ public class SyncStorageEngine extends Handler { } } - @Override public void handleMessage(Message msg) { - if (msg.what == MSG_WRITE_STATUS) { - synchronized (mAuthorities) { - writeStatusLocked(); - } - } else if (msg.what == MSG_WRITE_STATISTICS) { - synchronized (mAuthorities) { - writeStatisticsLocked(); + private class MyHandler extends Handler { + public MyHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + if (msg.what == MSG_WRITE_STATUS) { + synchronized (mAuthorities) { + writeStatusLocked(); + } + } else if (msg.what == MSG_WRITE_STATISTICS) { + synchronized (mAuthorities) { + writeStatisticsLocked(); + } } } } @@ -1202,14 +1213,14 @@ public class SyncStorageEngine extends Handler { if (writeStatusNow) { writeStatusLocked(); - } else if (!hasMessages(MSG_WRITE_STATUS)) { - sendMessageDelayed(obtainMessage(MSG_WRITE_STATUS), + } else if (!mHandler.hasMessages(MSG_WRITE_STATUS)) { + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_WRITE_STATUS), WRITE_STATUS_DELAY); } if (writeStatisticsNow) { writeStatisticsLocked(); - } else if (!hasMessages(MSG_WRITE_STATISTICS)) { - sendMessageDelayed(obtainMessage(MSG_WRITE_STATISTICS), + } else if (!mHandler.hasMessages(MSG_WRITE_STATISTICS)) { + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_WRITE_STATISTICS), WRITE_STATISTICS_DELAY); } } @@ -2102,7 +2113,7 @@ public class SyncStorageEngine extends Handler { // The file is being written, so we don't need to have a scheduled // write until the next change. - removeMessages(MSG_WRITE_STATUS); + mHandler.removeMessages(MSG_WRITE_STATUS); FileOutputStream fos = null; try { @@ -2210,7 +2221,7 @@ public class SyncStorageEngine extends Handler { // The file is being written, so we don't need to have a scheduled // write until the next change. - removeMessages(MSG_WRITE_STATISTICS); + mHandler.removeMessages(MSG_WRITE_STATISTICS); FileOutputStream fos = null; try { diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 9a6e609445a5..6c5bfc793330 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -24,6 +24,7 @@ import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; +import android.hardware.display.BrightnessConfiguration; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -34,7 +35,6 @@ import android.text.format.DateUtils; import android.util.EventLog; import android.util.MathUtils; import android.util.Slog; -import android.util.Spline; import android.util.TimeUtils; import java.io.PrintWriter; @@ -76,9 +76,8 @@ class AutomaticBrightnessController { // The light sensor, or null if not available or needed. private final Sensor mLightSensor; - // The auto-brightness spline adjustment. - // The brightness values have been scaled to a range of 0..1. - private final Spline mScreenAutoBrightnessSpline; + // The mapper to translate ambient lux to screen brightness in the range [0, 1.0]. + private final BrightnessMappingStrategy mBrightnessMapper; // The minimum and maximum screen brightnesses. private final int mScreenBrightnessRangeMinimum; @@ -186,7 +185,7 @@ class AutomaticBrightnessController { private float mBrightnessAdjustmentSampleOldGamma; public AutomaticBrightnessController(Callbacks callbacks, Looper looper, - SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime, + SensorManager sensorManager, BrightnessMappingStrategy mapper, int lightSensorWarmUpTime, int brightnessMin, int brightnessMax, float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig, long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig, @@ -194,7 +193,7 @@ class AutomaticBrightnessController { HysteresisLevels dynamicHysteresis) { mCallbacks = callbacks; mSensorManager = sensorManager; - mScreenAutoBrightnessSpline = autoBrightnessSpline; + mBrightnessMapper = mapper; mScreenBrightnessRangeMinimum = brightnessMin; mScreenBrightnessRangeMaximum = brightnessMax; mLightSensorWarmUpTimeConfig = lightSensorWarmUpTime; @@ -228,15 +227,16 @@ class AutomaticBrightnessController { return mScreenAutoBrightness; } - public void configure(boolean enable, float adjustment, boolean dozing, - boolean userInitiatedChange) { + public void configure(boolean enable, @Nullable BrightnessConfiguration configuration, + float adjustment, boolean dozing, boolean userInitiatedChange) { // While dozing, the application processor may be suspended which will prevent us from // receiving new information from the light sensor. On some devices, we may be able to // switch to a wake-up light sensor instead but for now we will simply disable the sensor // and hold onto the last computed screen auto brightness. We save the dozing flag for // debugging purposes. mDozing = dozing; - boolean changed = setLightSensorEnabled(enable && !dozing); + boolean changed = setBrightnessConfiguration(configuration); + changed |= setLightSensorEnabled(enable && !dozing); if (enable && !dozing && userInitiatedChange) { prepareBrightnessAdjustmentSample(); } @@ -246,10 +246,13 @@ class AutomaticBrightnessController { } } + public boolean setBrightnessConfiguration(BrightnessConfiguration configuration) { + return mBrightnessMapper.setBrightnessConfiguration(configuration); + } + public void dump(PrintWriter pw) { pw.println(); pw.println("Automatic Brightness Controller Configuration:"); - pw.println(" mScreenAutoBrightnessSpline=" + mScreenAutoBrightnessSpline); pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum); pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum); pw.println(" mLightSensorWarmUpTimeConfig=" + mLightSensorWarmUpTimeConfig); @@ -274,9 +277,13 @@ class AutomaticBrightnessController { mInitialHorizonAmbientLightRingBuffer); pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness); pw.println(" mScreenAutoBrightnessAdjustment=" + mScreenAutoBrightnessAdjustment); - pw.println(" mScreenAutoBrightnessAdjustmentMaxGamma=" + mScreenAutoBrightnessAdjustmentMaxGamma); + pw.println(" mScreenAutoBrightnessAdjustmentMaxGamma=" + + mScreenAutoBrightnessAdjustmentMaxGamma); pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma); pw.println(" mDozing=" + mDozing); + + pw.println(); + mBrightnessMapper.dump(pw); } private boolean setLightSensorEnabled(boolean enable) { @@ -533,7 +540,7 @@ class AutomaticBrightnessController { return; } - float value = mScreenAutoBrightnessSpline.interpolate(mAmbientLux); + float value = mBrightnessMapper.getBrightness(mAmbientLux); float gamma = 1.0f; if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java new file mode 100644 index 000000000000..3b9d40fa0825 --- /dev/null +++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java @@ -0,0 +1,289 @@ +/* + * 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.display; + +import android.annotation.Nullable; +import android.hardware.display.BrightnessConfiguration; +import android.os.PowerManager; +import android.util.MathUtils; +import android.util.Pair; +import android.util.Slog; +import android.util.Spline; + +import com.android.internal.util.Preconditions; +import com.android.internal.annotations.VisibleForTesting; + +import java.io.PrintWriter; + +/** + * A utility to map from an ambient brightness to a display's "backlight" brightness based on the + * available display information and brightness configuration. + * + * Note that without a mapping from the nits to a display backlight level, any + * {@link BrightnessConfiguration}s that are set are just ignored. + */ +public abstract class BrightnessMappingStrategy { + private static final String TAG = "BrightnessMappingStrategy"; + private static final boolean DEBUG = false; + + @Nullable + public static BrightnessMappingStrategy create( + float[] luxLevels, int[] brightnessLevelsBacklight, float[] brightnessLevelsNits, + float[] nitsRange, int[] backlightRange) { + if (isValidMapping(nitsRange, backlightRange) + && isValidMapping(luxLevels, brightnessLevelsNits)) { + BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(); + builder.setCurve(luxLevels, brightnessLevelsNits); + return new PhysicalMappingStrategy(builder.build(), nitsRange, backlightRange); + } else if (isValidMapping(luxLevels, brightnessLevelsBacklight)) { + return new SimpleMappingStrategy(luxLevels, brightnessLevelsBacklight); + } else { + return null; + } + } + + private static boolean isValidMapping(float[] x, float[] y) { + if (x == null || y == null || x.length == 0 || y.length == 0) { + return false; + } + if (x.length != y.length) { + return false; + } + final int N = x.length; + float prevX = x[0]; + float prevY = y[0]; + if (prevX < 0 || prevY < 0 || Float.isNaN(prevX) || Float.isNaN(prevY)) { + return false; + } + for (int i = 1; i < N; i++) { + if (prevX >= x[i] || prevY > y[i]) { + return false; + } + if (Float.isNaN(x[i]) || Float.isNaN(y[i])) { + return false; + } + prevX = x[i]; + prevY = y[i]; + } + return true; + } + + private static boolean isValidMapping(float[] x, int[] y) { + if (x == null || y == null || x.length == 0 || y.length == 0) { + return false; + } + if (x.length != y.length) { + return false; + } + final int N = x.length; + float prevX = x[0]; + int prevY = y[0]; + if (prevX < 0 || prevY < 0 || Float.isNaN(prevX)) { + return false; + } + for (int i = 1; i < N; i++) { + if (prevX >= x[i] || prevY > y[i]) { + return false; + } + if (Float.isNaN(x[i])) { + return false; + } + prevX = x[i]; + prevY = y[i]; + } + return true; + } + + /** + * Sets the {@link BrightnessConfiguration}. + * + * @param config The new configuration. If {@code null} is passed, the default configuration is + * used. + * @return Whether the brightness configuration has changed. + */ + public abstract boolean setBrightnessConfiguration(@Nullable BrightnessConfiguration config); + + /** + * Returns the desired brightness of the display based on the current ambient lux. + * + * The returned brightness will be in the range [0, 1.0], where 1.0 is the display at max + * brightness and 0 is the display at minimum brightness. + * + * @param lux The current ambient brightness in lux. + * @return The desired brightness of the display compressed to the range [0, 1.0]. + */ + public abstract float getBrightness(float lux); + + public abstract void dump(PrintWriter pw); + + private static float normalizeAbsoluteBrightness(int brightness) { + brightness = MathUtils.constrain(brightness, + PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON); + return (float) brightness / PowerManager.BRIGHTNESS_ON; + } + + + /** + * A {@link BrightnessMappingStrategy} that maps from ambient room brightness directly to the + * backlight of the display. + * + * Since we don't have information about the display's physical brightness, any brightness + * configurations that are set are just ignored. + */ + private static class SimpleMappingStrategy extends BrightnessMappingStrategy { + private final Spline mSpline; + + public SimpleMappingStrategy(float[] lux, int[] brightness) { + Preconditions.checkArgument(lux.length != 0 && brightness.length != 0, + "Lux and brightness arrays must not be empty!"); + Preconditions.checkArgument(lux.length == brightness.length, + "Lux and brightness arrays must be the same length!"); + Preconditions.checkArrayElementsInRange(lux, 0, Float.MAX_VALUE, "lux"); + Preconditions.checkArrayElementsInRange(brightness, + 0, Integer.MAX_VALUE, "brightness"); + + final int N = brightness.length; + float[] x = new float[N]; + float[] y = new float[N]; + for (int i = 0; i < N; i++) { + x[i] = lux[i]; + y[i] = normalizeAbsoluteBrightness(brightness[i]); + } + + mSpline = Spline.createSpline(x, y); + if (DEBUG) { + Slog.d(TAG, "Auto-brightness spline: " + mSpline); + for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) { + Slog.d(TAG, String.format(" %7.1f: %7.1f", v, mSpline.interpolate(v))); + } + } + } + + @Override + public boolean setBrightnessConfiguration(@Nullable BrightnessConfiguration config) { + Slog.e(TAG, + "setBrightnessConfiguration called on device without display information."); + return false; + } + + @Override + public float getBrightness(float lux) { + return mSpline.interpolate(lux); + } + + @Override + public void dump(PrintWriter pw) { + pw.println("SimpleMappingStrategy"); + pw.println(" mSpline=" + mSpline); + } + } + + /** A {@link BrightnessMappingStrategy} that maps from ambient room brightness to the physical + * range of the display, rather than to the range of the backlight control (typically 0-255). + * + * By mapping through the physical brightness, the curve becomes portable across devices and + * gives us more resolution in the resulting mapping. + */ + @VisibleForTesting + static class PhysicalMappingStrategy extends BrightnessMappingStrategy { + // The current brightness configuration. + private BrightnessConfiguration mConfig; + + // A spline mapping from the current ambient light in lux to the desired display brightness + // in nits. + private Spline mBrightnessSpline; + + // A spline mapping from nits to the corresponding backlight value, normalized to the range + // [0, 1.0]. + private final Spline mBacklightSpline; + + // The default brightness configuration. + private final BrightnessConfiguration mDefaultConfig; + + public PhysicalMappingStrategy(BrightnessConfiguration config, + float[] nits, int[] backlight) { + Preconditions.checkArgument(nits.length != 0 && backlight.length != 0, + "Nits and backlight arrays must not be empty!"); + Preconditions.checkArgument(nits.length == backlight.length, + "Nits and backlight arrays must be the same length!"); + Preconditions.checkNotNull(config); + Preconditions.checkArrayElementsInRange(nits, 0, Float.MAX_VALUE, "nits"); + Preconditions.checkArrayElementsInRange(backlight, + PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON, "backlight"); + + // Setup the backlight spline + final int N = nits.length; + float[] x = new float[N]; + float[] y = new float[N]; + for (int i = 0; i < N; i++) { + x[i] = nits[i]; + y[i] = normalizeAbsoluteBrightness(backlight[i]); + } + + mBacklightSpline = Spline.createSpline(x, y); + if (DEBUG) { + Slog.d(TAG, "Backlight spline: " + mBacklightSpline); + for (float v = 1f; v < nits[nits.length - 1] * 1.25f; v *= 1.25f) { + Slog.d(TAG, String.format( + " %7.1f: %7.1f", v, mBacklightSpline.interpolate(v))); + } + } + + mDefaultConfig = config; + setBrightnessConfiguration(config); + } + + @Override + public boolean setBrightnessConfiguration(@Nullable BrightnessConfiguration config) { + if (config == null) { + config = mDefaultConfig; + } + if (config.equals(mConfig)) { + if (DEBUG) { + Slog.d(TAG, "Tried to set an identical brightness config, ignoring"); + } + return false; + } + + Pair<float[], float[]> curve = config.getCurve(); + mBrightnessSpline = Spline.createSpline(curve.first /*lux*/, curve.second /*nits*/); + if (DEBUG) { + Slog.d(TAG, "Brightness spline: " + mBrightnessSpline); + final float[] lux = curve.first; + for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) { + Slog.d(TAG, String.format( + " %7.1f: %7.1f", v, mBrightnessSpline.interpolate(v))); + } + } + mConfig = config; + return true; + } + + @Override + public float getBrightness(float lux) { + return mBacklightSpline.interpolate(mBrightnessSpline.interpolate(lux)); + } + + @Override + public void dump(PrintWriter pw) { + pw.println("PhysicalMappingStrategy"); + pw.println(" mConfig=" + mConfig); + pw.println(" mBrightnessSpline=" + mBrightnessSpline); + pw.println(" mBacklightSpline=" + mBacklightSpline); + } + } +} diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java index 61b6fa073be9..42247f94e69f 100644 --- a/services/core/java/com/android/server/display/BrightnessTracker.java +++ b/services/core/java/com/android/server/display/BrightnessTracker.java @@ -500,13 +500,30 @@ public class BrightnessTracker { } public void dump(PrintWriter pw) { - synchronized (mEventsLock) { - pw.println("BrightnessTracker state:"); - pw.println(" mEvents.size=" + mEvents.size()); - pw.println(" mEventsDirty=" + mEventsDirty); - } + pw.println("BrightnessTracker state:"); synchronized (mDataCollectionLock) { pw.println(" mLastSensorReadings.size=" + mLastSensorReadings.size()); + if (!mLastSensorReadings.isEmpty()) { + pw.println(" mLastSensorReadings time span " + + mLastSensorReadings.peekFirst().timestamp + "->" + + mLastSensorReadings.peekLast().timestamp); + } + } + synchronized (mEventsLock) { + pw.println(" mEventsDirty=" + mEventsDirty); + pw.println(" mEvents.size=" + mEvents.size()); + BrightnessChangeEvent[] events = mEvents.toArray(); + for (int i = 0; i < events.length; ++i) { + pw.print(" " + events[i].timeStamp + ", " + events[i].userId); + pw.print(", " + events[i].lastBrightness + "->" + events[i].brightness + ", {"); + for (int j = 0; j < events[i].luxValues.length; ++j){ + if (j != 0) { + pw.print(", "); + } + pw.print("(" + events[i].luxValues[j] + "," + events[i].luxTimestamps[j] + ")"); + } + pw.println("}"); + } } } diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index c1bfa478ee89..9b97934cfc3b 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -29,6 +29,7 @@ import com.android.internal.util.IndentingPrintWriter; import android.Manifest; import android.annotation.NonNull; +import android.annotation.UserIdInt; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; @@ -37,6 +38,7 @@ import android.content.res.Resources; import android.graphics.Point; import android.hardware.SensorManager; import android.hardware.display.BrightnessChangeEvent; +import android.hardware.display.BrightnessConfiguration; import android.hardware.display.DisplayManagerGlobal; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayViewport; @@ -62,6 +64,7 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; +import android.os.UserManager; import android.text.TextUtils; import android.util.IntArray; import android.util.Slog; @@ -70,6 +73,7 @@ import android.view.Display; import android.view.DisplayInfo; import android.view.Surface; +import com.android.internal.util.Preconditions; import com.android.server.AnimationThread; import com.android.server.DisplayThread; import com.android.server.LocalServices; @@ -145,6 +149,7 @@ public final class DisplayManagerService extends SystemService { private static final int MSG_REQUEST_TRAVERSAL = 4; private static final int MSG_UPDATE_VIEWPORT = 5; private static final int MSG_REGISTER_BRIGHTNESS_TRACKER = 6; + private static final int MSG_LOAD_BRIGHTNESS_CONFIGURATION = 7; private final Context mContext; private final DisplayManagerHandler mHandler; @@ -219,6 +224,9 @@ public final class DisplayManagerService extends SystemService { // The virtual display adapter, or null if not registered. private VirtualDisplayAdapter mVirtualDisplayAdapter; + // The User ID of the current user + private @UserIdInt int mCurrentUserId; + // The stable device screen height and width. These are not tied to a specific display, even // the default display, because they need to be stable over the course of the device's entire // life, even if the default display changes (e.g. a new monitor is plugged into a PC-like @@ -278,17 +286,18 @@ public final class DisplayManagerService extends SystemService { mDisplayAdapterListener = new DisplayAdapterListener(); mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false); mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger( - com.android.internal.R.integer.config_defaultDisplayDefaultColorMode); + com.android.internal.R.integer.config_defaultDisplayDefaultColorMode); PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting(); mBrightnessTracker = new BrightnessTracker(context, null); + mCurrentUserId = UserHandle.USER_SYSTEM; } public void setupSchedulerPolicies() { // android.display and android.anim is critical to user experience and we should make sure - // it is not in the default foregroup groups, add it to top-app to make sure it uses all the - // cores and scheduling settings for top-app when it runs. + // it is not in the default foregroup groups, add it to top-app to make sure it uses all + // the cores and scheduling settings for top-app when it runs. Process.setThreadGroupAndCpuset(DisplayThread.get().getThreadId(), Process.THREAD_GROUP_TOP_APP); Process.setThreadGroupAndCpuset(AnimationThread.get().getThreadId(), @@ -342,6 +351,19 @@ public final class DisplayManagerService extends SystemService { } } + @Override + public void onSwitchUser(@UserIdInt int newUserId) { + final int userSerial = getUserManager().getUserSerialNumber(newUserId); + synchronized (mSyncRoot) { + if (mCurrentUserId != newUserId) { + mCurrentUserId = newUserId; + BrightnessConfiguration config = + mPersistentDataStore.getBrightnessConfiguration(userSerial); + mDisplayPowerController.setBrightnessConfiguration(config); + } + } + } + // TODO: Use dependencies or a boot phase public void windowManagerAndInputReady() { synchronized (mSyncRoot) { @@ -985,6 +1007,30 @@ public final class DisplayManagerService extends SystemService { } } + private void setBrightnessConfigurationForUserInternal( + @NonNull BrightnessConfiguration c, @UserIdInt int userId) { + final int userSerial = getUserManager().getUserSerialNumber(userId); + synchronized (mSyncRoot) { + try { + mPersistentDataStore.setBrightnessConfigurationForUser(c, userSerial); + } finally { + mPersistentDataStore.saveIfNeeded(); + } + if (userId == mCurrentUserId) { + mDisplayPowerController.setBrightnessConfiguration(c); + } + } + } + + private void loadBrightnessConfiguration() { + synchronized (mSyncRoot) { + final int userSerial = getUserManager().getUserSerialNumber(mCurrentUserId); + BrightnessConfiguration config = + mPersistentDataStore.getBrightnessConfiguration(userSerial); + mDisplayPowerController.setBrightnessConfiguration(config); + } + } + // Updates all existing logical displays given the current set of display devices. // Removes invalid logical displays. // Sends notifications if needed. @@ -1229,6 +1275,10 @@ public final class DisplayManagerService extends SystemService { return mProjectionService; } + private UserManager getUserManager() { + return mContext.getSystemService(UserManager.class); + } + private void dumpInternal(PrintWriter pw) { pw.println("DISPLAY MANAGER (dumpsys display)"); @@ -1371,6 +1421,10 @@ public final class DisplayManagerService extends SystemService { case MSG_REGISTER_BRIGHTNESS_TRACKER: mBrightnessTracker.start(); break; + + case MSG_LOAD_BRIGHTNESS_CONFIGURATION: + loadBrightnessConfiguration(); + break; } } } @@ -1800,6 +1854,27 @@ public final class DisplayManagerService extends SystemService { } } + @Override // Binder call + public void setBrightnessConfigurationForUser( + BrightnessConfiguration c, @UserIdInt int userId) { + mContext.enforceCallingOrSelfPermission( + Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS, + "Permission required to change the display's brightness configuration"); + if (userId != UserHandle.getCallingUserId()) { + mContext.enforceCallingOrSelfPermission( + Manifest.permission.INTERACT_ACROSS_USERS, + "Permission required to change the display brightness" + + " configuration of another user"); + } + Preconditions.checkNotNull(c); + final long token = Binder.clearCallingIdentity(); + try { + setBrightnessConfigurationForUserInternal(c, userId); + } finally { + Binder.restoreCallingIdentity(token); + } + } + private boolean validatePackageName(int uid, String packageName) { if (packageName != null) { String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid); @@ -1871,18 +1946,24 @@ public final class DisplayManagerService extends SystemService { mDisplayPowerController = new DisplayPowerController( mContext, callbacks, handler, sensorManager, blanker); } + + mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATION); } @Override public boolean requestPowerState(DisplayPowerRequest request, boolean waitForNegativeProximity) { - return mDisplayPowerController.requestPowerState(request, - waitForNegativeProximity); + synchronized (mSyncRoot) { + return mDisplayPowerController.requestPowerState(request, + waitForNegativeProximity); + } } @Override public boolean isProximitySensorAvailable() { - return mDisplayPowerController.isProximitySensorAvailable(); + synchronized (mSyncRoot) { + return mDisplayPowerController.isProximitySensorAvailable(); + } } @Override diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 29a007a36d41..a2d954822e64 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -26,10 +26,12 @@ import android.animation.Animator; import android.animation.ObjectAnimator; import android.content.Context; import android.content.res.Resources; +import android.content.res.TypedArray; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; +import android.hardware.display.BrightnessConfiguration; import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks; import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest; import android.os.Handler; @@ -93,6 +95,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2; private static final int MSG_SCREEN_ON_UNBLOCKED = 3; private static final int MSG_SCREEN_OFF_UNBLOCKED = 4; + private static final int MSG_CONFIGURE_BRIGHTNESS = 5; + private static final int MSG_USER_SWITCH = 6; private static final int PROXIMITY_UNKNOWN = -1; private static final int PROXIMITY_NEGATIVE = 0; @@ -285,6 +289,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // The controller for the automatic brightness level. private AutomaticBrightnessController mAutomaticBrightnessController; + // The default brightness configuration. Used for whenever we don't have a valid brightness + // configuration set. This is typically seen with users that don't have a brightness + // configuration that's different from the default. + private BrightnessConfiguration mDefaultBrightnessConfiguration; + + // The current brightness configuration. + private BrightnessConfiguration mBrightnessConfiguration; + // Animators. private ObjectAnimator mColorFadeOnAnimator; private ObjectAnimator mColorFadeOffAnimator; @@ -333,7 +345,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call screenBrightnessSettingMinimum, mScreenBrightnessDimConfig), mScreenBrightnessDarkConfig); - mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON; + mScreenBrightnessRangeMaximum = clampAbsoluteBrightness(resources.getInteger( + com.android.internal.R.integer.config_screenBrightnessSettingMaximum)); mUseSoftwareAutoBrightnessConfig = resources.getBoolean( com.android.internal.R.bool.config_automatic_brightness_available); @@ -348,60 +361,60 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mSkipScreenOnBrightnessRamp = resources.getBoolean( com.android.internal.R.bool.config_skipScreenOnBrightnessRamp); - int lightSensorRate = resources.getInteger( - com.android.internal.R.integer.config_autoBrightnessLightSensorRate); - int initialLightSensorRate = resources.getInteger( - com.android.internal.R.integer.config_autoBrightnessInitialLightSensorRate); - if (initialLightSensorRate == -1) { - initialLightSensorRate = lightSensorRate; - } else if (initialLightSensorRate > lightSensorRate) { - Slog.w(TAG, "Expected config_autoBrightnessInitialLightSensorRate (" - + initialLightSensorRate + ") to be less than or equal to " - + "config_autoBrightnessLightSensorRate (" + lightSensorRate + ")."); - } - long brighteningLightDebounce = resources.getInteger( - com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce); - long darkeningLightDebounce = resources.getInteger( - com.android.internal.R.integer.config_autoBrightnessDarkeningLightDebounce); - boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean( - com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp); - int ambientLightHorizon = resources.getInteger( - com.android.internal.R.integer.config_autoBrightnessAmbientLightHorizon); - float autoBrightnessAdjustmentMaxGamma = resources.getFraction( - com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma, - 1, 1); - - int[] brightLevels = resources.getIntArray( - com.android.internal.R.array.config_dynamicHysteresisBrightLevels); - int[] darkLevels = resources.getIntArray( - com.android.internal.R.array.config_dynamicHysteresisDarkLevels); - int[] luxLevels = resources.getIntArray( - com.android.internal.R.array.config_dynamicHysteresisLuxLevels); - HysteresisLevels dynamicHysteresis = new HysteresisLevels( - brightLevels, darkLevels, luxLevels); - if (mUseSoftwareAutoBrightnessConfig) { - int[] lux = resources.getIntArray( - com.android.internal.R.array.config_autoBrightnessLevels); - int[] screenBrightness = resources.getIntArray( + float[] luxLevels = getLuxLevels(resources.getIntArray( + com.android.internal.R.array.config_autoBrightnessLevels)); + int[] backlightValues = resources.getIntArray( com.android.internal.R.array.config_autoBrightnessLcdBacklightValues); - int lightSensorWarmUpTimeConfig = resources.getInteger( - com.android.internal.R.integer.config_lightSensorWarmupTime); + float[] brightnessValuesNits = getFloatArray(resources.obtainTypedArray( + com.android.internal.R.array.config_autoBrightnessDisplayValuesNits)); + + final float screenMinimumNits = resources.getFloat( + com.android.internal.R.dimen.config_screenBrightnessMinimumNits); + final float screenMaximumNits = resources.getFloat( + com.android.internal.R.dimen.config_screenBrightnessMaximumNits); + final float dozeScaleFactor = resources.getFraction( com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor, 1, 1); - Spline screenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness); - if (screenAutoBrightnessSpline == null) { - Slog.e(TAG, "Error in config.xml. config_autoBrightnessLcdBacklightValues " - + "(size " + screenBrightness.length + ") " - + "must be monotic and have exactly one more entry than " - + "config_autoBrightnessLevels (size " + lux.length + ") " - + "which must be strictly increasing. " - + "Auto-brightness will be disabled."); - mUseSoftwareAutoBrightnessConfig = false; - } else { - int bottom = clampAbsoluteBrightness(screenBrightness[0]); + int[] brightLevels = resources.getIntArray( + com.android.internal.R.array.config_dynamicHysteresisBrightLevels); + int[] darkLevels = resources.getIntArray( + com.android.internal.R.array.config_dynamicHysteresisDarkLevels); + int[] luxHysteresisLevels = resources.getIntArray( + com.android.internal.R.array.config_dynamicHysteresisLuxLevels); + HysteresisLevels dynamicHysteresis = new HysteresisLevels( + brightLevels, darkLevels, luxHysteresisLevels); + + long brighteningLightDebounce = resources.getInteger( + com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce); + long darkeningLightDebounce = resources.getInteger( + com.android.internal.R.integer.config_autoBrightnessDarkeningLightDebounce); + boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean( + com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp); + int ambientLightHorizon = resources.getInteger( + com.android.internal.R.integer.config_autoBrightnessAmbientLightHorizon); + float autoBrightnessAdjustmentMaxGamma = resources.getFraction( + com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma, + 1, 1); + + int lightSensorWarmUpTimeConfig = resources.getInteger( + com.android.internal.R.integer.config_lightSensorWarmupTime); + int lightSensorRate = resources.getInteger( + com.android.internal.R.integer.config_autoBrightnessLightSensorRate); + int initialLightSensorRate = resources.getInteger( + com.android.internal.R.integer.config_autoBrightnessInitialLightSensorRate); + if (initialLightSensorRate == -1) { + initialLightSensorRate = lightSensorRate; + } else if (initialLightSensorRate > lightSensorRate) { + Slog.w(TAG, "Expected config_autoBrightnessInitialLightSensorRate (" + + initialLightSensorRate + ") to be less than or equal to " + + "config_autoBrightnessLightSensorRate (" + lightSensorRate + ")."); + } + + if (backlightValues != null && backlightValues.length > 0) { + final int bottom = backlightValues[0]; if (mScreenBrightnessDarkConfig > bottom) { Slog.w(TAG, "config_screenBrightnessDark (" + mScreenBrightnessDarkConfig + ") should be less than or equal to the first value of " @@ -411,13 +424,24 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call if (bottom < screenBrightnessRangeMinimum) { screenBrightnessRangeMinimum = bottom; } + } + + float[] nitsRange = { screenMinimumNits, screenMaximumNits }; + int[] backlightRange = { screenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum }; + + BrightnessMappingStrategy mapper = BrightnessMappingStrategy.create( + luxLevels, backlightValues, brightnessValuesNits, + nitsRange, backlightRange); + if (mapper != null) { mAutomaticBrightnessController = new AutomaticBrightnessController(this, - handler.getLooper(), sensorManager, screenAutoBrightnessSpline, - lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum, - mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate, - initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce, + handler.getLooper(), sensorManager, mapper, lightSensorWarmUpTimeConfig, + screenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum, + dozeScaleFactor, lightSensorRate, initialLightSensorRate, + brighteningLightDebounce, darkeningLightDebounce, autoBrightnessResetAmbientLuxAfterWarmUp, ambientLightHorizon, autoBrightnessAdjustmentMaxGamma, dynamicHysteresis); + } else { + mUseSoftwareAutoBrightnessConfig = false; } } @@ -444,6 +468,25 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } + private static float[] getLuxLevels(int[] lux) { + // The first control point is implicit and always at 0 lux. + float[] levels = new float[lux.length + 1]; + for (int i = 0; i < lux.length; i++) { + levels[i + 1] = (float) lux[i]; + } + return levels; + } + + private static float[] getFloatArray(TypedArray array) { + final int N = array.length(); + float[] vals = new float[N]; + for (int i = 0; i < N; i++) { + vals[i] = array.getFloat(i, -1.0f); + } + array.recycle(); + return vals; + } + /** * Returns true if the proximity sensor screen-off function is available. */ @@ -512,7 +555,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call if (!mPendingUpdatePowerStateLocked) { mPendingUpdatePowerStateLocked = true; Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE); - msg.setAsynchronous(true); mHandler.sendMessage(msg); } } @@ -691,8 +733,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call final boolean userInitiatedChange = autoBrightnessAdjustmentChanged && mPowerRequest.brightnessSetByUser; mAutomaticBrightnessController.configure(autoBrightnessEnabled, - mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON, - userInitiatedChange); + mBrightnessConfiguration, mPowerRequest.screenAutoBrightnessAdjustment, + state != Display.STATE_ON, userInitiatedChange); } // Apply brightness boost. @@ -874,6 +916,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call sendUpdatePowerState(); } + public void setBrightnessConfiguration(BrightnessConfiguration c) { + Message msg = mHandler.obtainMessage(MSG_CONFIGURE_BRIGHTNESS, c); + msg.sendToTarget(); + } + private void blockScreenOn() { if (mPendingScreenOnUnblocker == null) { Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0); @@ -1241,7 +1288,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // Need to wait a little longer. // Debounce again later. We continue holding a wake lock while waiting. Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED); - msg.setAsynchronous(true); mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime); } } @@ -1402,39 +1448,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } } - private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) { - if (lux == null || lux.length == 0 || brightness == null || brightness.length == 0) { - Slog.e(TAG, "Could not create auto-brightness spline."); - return null; - } - try { - final int n = brightness.length; - float[] x = new float[n]; - float[] y = new float[n]; - y[0] = normalizeAbsoluteBrightness(brightness[0]); - for (int i = 1; i < n; i++) { - x[i] = lux[i - 1]; - y[i] = normalizeAbsoluteBrightness(brightness[i]); - } - - Spline spline = Spline.createSpline(x, y); - if (DEBUG) { - Slog.d(TAG, "Auto-brightness spline: " + spline); - for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) { - Slog.d(TAG, String.format(" %7.1f: %7.1f", v, spline.interpolate(v))); - } - } - return spline; - } catch (IllegalArgumentException ex) { - Slog.e(TAG, "Could not create auto-brightness spline.", ex); - return null; - } - } - - private static float normalizeAbsoluteBrightness(int value) { - return (float)clampAbsoluteBrightness(value) / PowerManager.BRIGHTNESS_ON; - } - private static int clampAbsoluteBrightness(int value) { return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON); } @@ -1467,6 +1480,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call updatePowerState(); } break; + case MSG_CONFIGURE_BRIGHTNESS: + BrightnessConfiguration c = (BrightnessConfiguration) msg.obj; + mBrightnessConfiguration = c != null ? c : mDefaultBrightnessConfiguration; + updatePowerState(); + break; } } } @@ -1492,17 +1510,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call @Override public void onScreenOn() { Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this); - msg.setAsynchronous(true); mHandler.sendMessage(msg); } } private final class ScreenOffUnblocker implements WindowManagerPolicy.ScreenOffListener { - @Override public void onScreenOff() { Message msg = mHandler.obtainMessage(MSG_SCREEN_OFF_UNBLOCKED, this); - msg.setAsynchronous(true); mHandler.sendMessage(msg); } } diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java index 34c8e22a9f1e..49b4465efac7 100644 --- a/services/core/java/com/android/server/display/PersistentDataStore.java +++ b/services/core/java/com/android/server/display/PersistentDataStore.java @@ -24,12 +24,17 @@ import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import android.graphics.Point; +import android.hardware.display.BrightnessConfiguration; import android.hardware.display.WifiDisplay; import android.util.AtomicFile; import android.util.Slog; +import android.util.SparseArray; +import android.util.Pair; import android.util.Xml; import android.view.Display; +import com.android.internal.annotations.VisibleForTesting; + import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; @@ -37,10 +42,12 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import libcore.io.IoUtils; @@ -57,14 +64,22 @@ import libcore.util.Objects; * <wifi-display deviceAddress="00:00:00:00:00:00" deviceName="XXXX" deviceAlias="YYYY" /> * <remembered-wifi-displays> * <display-states> - * <display> + * <display unique-id="XXXXXXX"> * <color-mode>0</color-mode> * </display> * </display-states> * <stable-device-values> - * <stable-display-height>1920<stable-display-height> - * <stable-display-width>1080<stable-display-width> + * <stable-display-height>1920</stable-display-height> + * <stable-display-width>1080</stable-display-width> * </stable-device-values> + * <brightness-configurations> + * <brightness-configuration user-id="0"> + * <brightness-curve> + * <brightness-point lux="0" nits="13.25"/> + * <brightness-point lux="20" nits="35.94"/> + * </brightness-curve> + * </brightness-configuration> + * </brightness-configurations> * </display-manager-state> * </code> * @@ -73,6 +88,31 @@ import libcore.util.Objects; final class PersistentDataStore { static final String TAG = "DisplayManager"; + private static final String TAG_DISPLAY_MANAGER_STATE = "display-manager-state"; + + private static final String TAG_REMEMBERED_WIFI_DISPLAYS = "remembered-wifi-displays"; + private static final String TAG_WIFI_DISPLAY = "wifi-display"; + private static final String ATTR_DEVICE_ADDRESS = "deviceAddress"; + private static final String ATTR_DEVICE_NAME = "deviceName"; + private static final String ATTR_DEVICE_ALIAS = "deviceAlias"; + + private static final String TAG_DISPLAY_STATES = "display-states"; + private static final String TAG_DISPLAY = "display"; + private static final String TAG_COLOR_MODE = "color-mode"; + private static final String ATTR_UNIQUE_ID = "unique-id"; + + private static final String TAG_STABLE_DEVICE_VALUES = "stable-device-values"; + private static final String TAG_STABLE_DISPLAY_HEIGHT = "stable-display-height"; + private static final String TAG_STABLE_DISPLAY_WIDTH = "stable-display-width"; + + private static final String TAG_BRIGHTNESS_CONFIGURATIONS = "brightness-configurations"; + private static final String TAG_BRIGHTNESS_CONFIGURATION = "brightness-configuration"; + private static final String TAG_BRIGHTNESS_CURVE = "brightness-curve"; + private static final String TAG_BRIGHTNESS_POINT = "brightness-point"; + private static final String ATTR_USER_SERIAL = "user-serial"; + private static final String ATTR_LUX = "lux"; + private static final String ATTR_NITS = "nits"; + // Remembered Wifi display devices. private ArrayList<WifiDisplay> mRememberedWifiDisplays = new ArrayList<WifiDisplay>(); @@ -83,8 +123,8 @@ final class PersistentDataStore { // Display values which should be stable across the device's lifetime. private final StableDeviceValues mStableDeviceValues = new StableDeviceValues(); - // The atomic file used to safely read or write the file. - private final AtomicFile mAtomicFile; + // Brightness configuration by user + private BrightnessConfigurations mBrightnessConfigurations = new BrightnessConfigurations(); // True if the data has been loaded. private boolean mLoaded; @@ -92,8 +132,16 @@ final class PersistentDataStore { // True if there are changes to be saved. private boolean mDirty; + // The interface for methods which should be replaced by the test harness. + private Injector mInjector; + public PersistentDataStore() { - mAtomicFile = new AtomicFile(new File("/data/system/display-manager-state.xml")); + this(new Injector()); + } + + @VisibleForTesting + PersistentDataStore(Injector injector) { + mInjector = injector; } public void saveIfNeeded() { @@ -225,6 +273,18 @@ final class PersistentDataStore { } } + public void setBrightnessConfigurationForUser(BrightnessConfiguration c, int userSerial) { + loadIfNeeded(); + if (mBrightnessConfigurations.setBrightnessConfigurationForUser(c, userSerial)) { + setDirty(); + } + } + + public BrightnessConfiguration getBrightnessConfiguration(int userSerial) { + loadIfNeeded(); + return mBrightnessConfigurations.getBrightnessConfiguration(userSerial); + } + private DisplayState getDisplayState(String uniqueId, boolean createIfAbsent) { loadIfNeeded(); DisplayState state = mDisplayStates.get(uniqueId); @@ -256,7 +316,7 @@ final class PersistentDataStore { final InputStream is; try { - is = mAtomicFile.openRead(); + is = mInjector.openRead(); } catch (FileNotFoundException ex) { return; } @@ -278,9 +338,9 @@ final class PersistentDataStore { } private void save() { - final FileOutputStream os; + final OutputStream os; try { - os = mAtomicFile.startWrite(); + os = mInjector.startWrite(); boolean success = false; try { XmlSerializer serializer = new FastXmlSerializer(); @@ -289,11 +349,7 @@ final class PersistentDataStore { serializer.flush(); success = true; } finally { - if (success) { - mAtomicFile.finishWrite(os); - } else { - mAtomicFile.failWrite(os); - } + mInjector.finishWrite(os, success); } } catch (IOException ex) { Slog.w(TAG, "Failed to save display manager persistent store data.", ex); @@ -302,18 +358,21 @@ final class PersistentDataStore { private void loadFromXml(XmlPullParser parser) throws IOException, XmlPullParserException { - XmlUtils.beginDocument(parser, "display-manager-state"); + XmlUtils.beginDocument(parser, TAG_DISPLAY_MANAGER_STATE); final int outerDepth = parser.getDepth(); while (XmlUtils.nextElementWithin(parser, outerDepth)) { - if (parser.getName().equals("remembered-wifi-displays")) { + if (parser.getName().equals(TAG_REMEMBERED_WIFI_DISPLAYS)) { loadRememberedWifiDisplaysFromXml(parser); } - if (parser.getName().equals("display-states")) { + if (parser.getName().equals(TAG_DISPLAY_STATES)) { loadDisplaysFromXml(parser); } - if (parser.getName().equals("stable-device-values")) { + if (parser.getName().equals(TAG_STABLE_DEVICE_VALUES)) { mStableDeviceValues.loadFromXml(parser); } + if (parser.getName().equals(TAG_BRIGHTNESS_CONFIGURATIONS)) { + mBrightnessConfigurations.loadFromXml(parser); + } } } @@ -321,10 +380,10 @@ final class PersistentDataStore { throws IOException, XmlPullParserException { final int outerDepth = parser.getDepth(); while (XmlUtils.nextElementWithin(parser, outerDepth)) { - if (parser.getName().equals("wifi-display")) { - String deviceAddress = parser.getAttributeValue(null, "deviceAddress"); - String deviceName = parser.getAttributeValue(null, "deviceName"); - String deviceAlias = parser.getAttributeValue(null, "deviceAlias"); + if (parser.getName().equals(TAG_WIFI_DISPLAY)) { + String deviceAddress = parser.getAttributeValue(null, ATTR_DEVICE_ADDRESS); + String deviceName = parser.getAttributeValue(null, ATTR_DEVICE_NAME); + String deviceAlias = parser.getAttributeValue(null, ATTR_DEVICE_ALIAS); if (deviceAddress == null || deviceName == null) { throw new XmlPullParserException( "Missing deviceAddress or deviceName attribute on wifi-display."); @@ -345,8 +404,8 @@ final class PersistentDataStore { throws IOException, XmlPullParserException { final int outerDepth = parser.getDepth(); while (XmlUtils.nextElementWithin(parser, outerDepth)) { - if (parser.getName().equals("display")) { - String uniqueId = parser.getAttributeValue(null, "unique-id"); + if (parser.getName().equals(TAG_DISPLAY)) { + String uniqueId = parser.getAttributeValue(null, ATTR_UNIQUE_ID); if (uniqueId == null) { throw new XmlPullParserException( "Missing unique-id attribute on display."); @@ -365,32 +424,35 @@ final class PersistentDataStore { private void saveToXml(XmlSerializer serializer) throws IOException { serializer.startDocument(null, true); serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); - serializer.startTag(null, "display-manager-state"); - serializer.startTag(null, "remembered-wifi-displays"); + serializer.startTag(null, TAG_DISPLAY_MANAGER_STATE); + serializer.startTag(null, TAG_REMEMBERED_WIFI_DISPLAYS); for (WifiDisplay display : mRememberedWifiDisplays) { - serializer.startTag(null, "wifi-display"); - serializer.attribute(null, "deviceAddress", display.getDeviceAddress()); - serializer.attribute(null, "deviceName", display.getDeviceName()); + serializer.startTag(null, TAG_WIFI_DISPLAY); + serializer.attribute(null, ATTR_DEVICE_ADDRESS, display.getDeviceAddress()); + serializer.attribute(null, ATTR_DEVICE_NAME, display.getDeviceName()); if (display.getDeviceAlias() != null) { - serializer.attribute(null, "deviceAlias", display.getDeviceAlias()); + serializer.attribute(null, ATTR_DEVICE_ALIAS, display.getDeviceAlias()); } - serializer.endTag(null, "wifi-display"); + serializer.endTag(null, TAG_WIFI_DISPLAY); } - serializer.endTag(null, "remembered-wifi-displays"); - serializer.startTag(null, "display-states"); + serializer.endTag(null, TAG_REMEMBERED_WIFI_DISPLAYS); + serializer.startTag(null, TAG_DISPLAY_STATES); for (Map.Entry<String, DisplayState> entry : mDisplayStates.entrySet()) { final String uniqueId = entry.getKey(); final DisplayState state = entry.getValue(); - serializer.startTag(null, "display"); - serializer.attribute(null, "unique-id", uniqueId); + serializer.startTag(null, TAG_DISPLAY); + serializer.attribute(null, ATTR_UNIQUE_ID, uniqueId); state.saveToXml(serializer); - serializer.endTag(null, "display"); + serializer.endTag(null, TAG_DISPLAY); } - serializer.endTag(null, "display-states"); - serializer.startTag(null, "stable-device-values"); + serializer.endTag(null, TAG_DISPLAY_STATES); + serializer.startTag(null, TAG_STABLE_DEVICE_VALUES); mStableDeviceValues.saveToXml(serializer); - serializer.endTag(null, "stable-device-values"); - serializer.endTag(null, "display-manager-state"); + serializer.endTag(null, TAG_STABLE_DEVICE_VALUES); + serializer.startTag(null, TAG_BRIGHTNESS_CONFIGURATIONS); + mBrightnessConfigurations.saveToXml(serializer); + serializer.endTag(null, TAG_BRIGHTNESS_CONFIGURATIONS); + serializer.endTag(null, TAG_DISPLAY_MANAGER_STATE); serializer.endDocument(); } @@ -411,6 +473,8 @@ final class PersistentDataStore { } pw.println(" StableDeviceValues:"); mStableDeviceValues.dump(pw, " "); + pw.println(" BrightnessConfigurations:"); + mBrightnessConfigurations.dump(pw, " "); } private static final class DisplayState { @@ -433,7 +497,7 @@ final class PersistentDataStore { final int outerDepth = parser.getDepth(); while (XmlUtils.nextElementWithin(parser, outerDepth)) { - if (parser.getName().equals("color-mode")) { + if (parser.getName().equals(TAG_COLOR_MODE)) { String value = parser.nextText(); mColorMode = Integer.parseInt(value); } @@ -441,9 +505,9 @@ final class PersistentDataStore { } public void saveToXml(XmlSerializer serializer) throws IOException { - serializer.startTag(null, "color-mode"); + serializer.startTag(null, TAG_COLOR_MODE); serializer.text(Integer.toString(mColorMode)); - serializer.endTag(null, "color-mode"); + serializer.endTag(null, TAG_COLOR_MODE); } public void dump(final PrintWriter pw, final String prefix) { @@ -472,10 +536,10 @@ final class PersistentDataStore { final int outerDepth = parser.getDepth(); while (XmlUtils.nextElementWithin(parser, outerDepth)) { switch (parser.getName()) { - case "stable-display-width": + case TAG_STABLE_DISPLAY_WIDTH: mWidth = loadIntValue(parser); break; - case "stable-display-height": + case TAG_STABLE_DISPLAY_HEIGHT: mHeight = loadIntValue(parser); break; } @@ -494,12 +558,12 @@ final class PersistentDataStore { public void saveToXml(XmlSerializer serializer) throws IOException { if (mWidth > 0 && mHeight > 0) { - serializer.startTag(null, "stable-display-width"); + serializer.startTag(null, TAG_STABLE_DISPLAY_WIDTH); serializer.text(Integer.toString(mWidth)); - serializer.endTag(null, "stable-display-width"); - serializer.startTag(null, "stable-display-height"); + serializer.endTag(null, TAG_STABLE_DISPLAY_WIDTH); + serializer.startTag(null, TAG_STABLE_DISPLAY_HEIGHT); serializer.text(Integer.toString(mHeight)); - serializer.endTag(null, "stable-display-height"); + serializer.endTag(null, TAG_STABLE_DISPLAY_HEIGHT); } } @@ -508,4 +572,158 @@ final class PersistentDataStore { pw.println(prefix + "StableDisplayHeight=" + mHeight); } } + + private static final class BrightnessConfigurations { + // Maps from a user ID to the users' given brightness configuration + private SparseArray<BrightnessConfiguration> mConfigurations; + + public BrightnessConfigurations() { + mConfigurations = new SparseArray<>(); + } + + private boolean setBrightnessConfigurationForUser(BrightnessConfiguration c, + int userSerial) { + BrightnessConfiguration currentConfig = mConfigurations.get(userSerial); + if (currentConfig == null || !currentConfig.equals(c)) { + mConfigurations.put(userSerial, c); + return true; + } + return false; + } + + public BrightnessConfiguration getBrightnessConfiguration(int userSerial) { + return mConfigurations.get(userSerial); + } + + public void loadFromXml(XmlPullParser parser) throws IOException, XmlPullParserException { + final int outerDepth = parser.getDepth(); + while (XmlUtils.nextElementWithin(parser, outerDepth)) { + if (TAG_BRIGHTNESS_CONFIGURATION.equals(parser.getName())) { + int userSerial; + try { + userSerial = Integer.parseInt( + parser.getAttributeValue(null, ATTR_USER_SERIAL)); + } catch (NumberFormatException nfe) { + userSerial= -1; + Slog.e(TAG, "Failed to read in brightness configuration", nfe); + } + + try { + BrightnessConfiguration config = loadConfigurationFromXml(parser); + if (userSerial>= 0 && config != null) { + mConfigurations.put(userSerial, config); + } + } catch (IllegalArgumentException iae) { + Slog.e(TAG, "Failed to load brightness configuration!", iae); + } + } + } + } + + private static BrightnessConfiguration loadConfigurationFromXml(XmlPullParser parser) + throws IOException, XmlPullParserException { + final int outerDepth = parser.getDepth(); + final BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(); + while (XmlUtils.nextElementWithin(parser, outerDepth)) { + if (TAG_BRIGHTNESS_CURVE.equals(parser.getName())) { + Pair<float[], float[]> curve = loadCurveFromXml(parser, builder); + builder.setCurve(curve.first /*lux*/, curve.second /*nits*/); + } + } + return builder.build(); + } + + private static Pair<float[], float[]> loadCurveFromXml(XmlPullParser parser, + BrightnessConfiguration.Builder builder) + throws IOException, XmlPullParserException { + final int outerDepth = parser.getDepth(); + List<Float> luxLevels = new ArrayList<>(); + List<Float> nitLevels = new ArrayList<>(); + while (XmlUtils.nextElementWithin(parser, outerDepth)) { + if (TAG_BRIGHTNESS_POINT.equals(parser.getName())) { + luxLevels.add(loadFloat(parser.getAttributeValue(null, ATTR_LUX))); + nitLevels.add(loadFloat(parser.getAttributeValue(null, ATTR_NITS))); + } + } + final int N = luxLevels.size(); + float[] lux = new float[N]; + float[] nits = new float[N]; + for (int i = 0; i < N; i++) { + lux[i] = luxLevels.get(i); + nits[i] = nitLevels.get(i); + } + return Pair.create(lux, nits); + } + + private static float loadFloat(String val) { + try { + return Float.parseFloat(val); + } catch (NullPointerException | NumberFormatException e) { + Slog.e(TAG, "Failed to parse float loading brightness config", e); + return Float.NEGATIVE_INFINITY; + } + } + + public void saveToXml(XmlSerializer serializer) throws IOException { + for (int i = 0; i < mConfigurations.size(); i++) { + final int userSerial= mConfigurations.keyAt(i); + final BrightnessConfiguration config = mConfigurations.valueAt(i); + + serializer.startTag(null, TAG_BRIGHTNESS_CONFIGURATION); + serializer.attribute(null, ATTR_USER_SERIAL, Integer.toString(userSerial)); + saveConfigurationToXml(serializer, config); + serializer.endTag(null, TAG_BRIGHTNESS_CONFIGURATION); + } + } + + private static void saveConfigurationToXml(XmlSerializer serializer, + BrightnessConfiguration config) throws IOException { + serializer.startTag(null, TAG_BRIGHTNESS_CURVE); + final Pair<float[], float[]> curve = config.getCurve(); + for (int i = 0; i < curve.first.length; i++) { + serializer.startTag(null, TAG_BRIGHTNESS_POINT); + serializer.attribute(null, ATTR_LUX, Float.toString(curve.first[i])); + serializer.attribute(null, ATTR_NITS, Float.toString(curve.second[i])); + serializer.endTag(null, TAG_BRIGHTNESS_POINT); + } + serializer.endTag(null, TAG_BRIGHTNESS_CURVE); + } + + public void dump(final PrintWriter pw, final String prefix) { + for (int i = 0; i < mConfigurations.size(); i++) { + final int userSerial= mConfigurations.keyAt(i); + pw.println(prefix + "User " + userSerial + ":"); + pw.println(prefix + " " + mConfigurations.valueAt(i)); + } + } + } + + @VisibleForTesting + static class Injector { + private final AtomicFile mAtomicFile; + + public Injector() { + mAtomicFile = new AtomicFile(new File("/data/system/display-manager-state.xml")); + } + + public InputStream openRead() throws FileNotFoundException { + return mAtomicFile.openRead(); + } + + public OutputStream startWrite() throws IOException { + return mAtomicFile.startWrite(); + } + + public void finishWrite(OutputStream os, boolean success) { + if (!(os instanceof FileOutputStream)) { + throw new IllegalArgumentException("Unexpected OutputStream as argument: " + os); + } + FileOutputStream fos = (FileOutputStream) os; + if (success) { + mAtomicFile.finishWrite(fos); + } else { + mAtomicFile.failWrite(fos); + } + } + } } diff --git a/services/core/java/com/android/server/job/JobSchedulerInternal.java b/services/core/java/com/android/server/job/JobSchedulerInternal.java index 9bcf208ab3f0..c97eeaf30ab3 100644 --- a/services/core/java/com/android/server/job/JobSchedulerInternal.java +++ b/services/core/java/com/android/server/job/JobSchedulerInternal.java @@ -44,6 +44,11 @@ public interface JobSchedulerInternal { List<JobInfo> getSystemScheduledPendingJobs(); /** + * Cancel the jobs for a given uid (e.g. when app data is cleared) + */ + void cancelJobsForUid(int uid, String reason); + + /** * These are for activity manager to communicate to use what is currently performing backups. */ void addBackingUpUid(int uid); diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index f2a1c4726e1c..009f10e74336 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -1997,6 +1997,11 @@ public final class JobSchedulerService extends com.android.server.SystemService } @Override + public void cancelJobsForUid(int uid, String reason) { + JobSchedulerService.this.cancelJobsForUid(uid, reason); + } + + @Override public void addBackingUpUid(int uid) { synchronized (mLock) { // No need to actually do anything here, since for a full backup the diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java index 219bc6114c79..36cacd7a7d96 100644 --- a/services/core/java/com/android/server/job/JobStore.java +++ b/services/core/java/com/android/server/job/JobStore.java @@ -1149,8 +1149,10 @@ public final class JobStore { public void forEachJob(JobStatusFunctor functor) { for (int uidIndex = mJobs.size() - 1; uidIndex >= 0; uidIndex--) { ArraySet<JobStatus> jobs = mJobs.valueAt(uidIndex); - for (int i = jobs.size() - 1; i >= 0; i--) { - functor.process(jobs.valueAt(i)); + if (jobs != null) { + for (int i = jobs.size() - 1; i >= 0; i--) { + functor.process(jobs.valueAt(i)); + } } } } diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java index 4525a4982d44..cd4bb14ee91f 100644 --- a/services/core/java/com/android/server/location/ContextHubService.java +++ b/services/core/java/com/android/server/location/ContextHubService.java @@ -742,6 +742,82 @@ public class ContextHubService extends IContextHubService.Stub { return mClientManager.registerClient(clientCallback, contextHubId); } + /** + * Loads a nanoapp binary at the specified Context hub. + * + * @param contextHubId the ID of the hub to load the binary + * @param transactionCallback the client-facing transaction callback interface + * @param nanoAppBinary the binary to load + * + * @throws RemoteException + */ + @Override + public void loadNanoAppOnHub( + int contextHubId, IContextHubTransactionCallback transactionCallback, + NanoAppBinary nanoAppBinary) throws RemoteException { + checkPermissions(); + if (!checkHalProxyAndContextHubId( + contextHubId, transactionCallback, ContextHubTransaction.TYPE_LOAD_NANOAPP)) { + return; + } + if (nanoAppBinary == null) { + Log.e(TAG, "NanoAppBinary cannot be null in loadNanoAppOnHub"); + transactionCallback.onTransactionComplete( + ContextHubTransaction.TRANSACTION_FAILED_BAD_PARAMS); + return; + } + + ContextHubServiceTransaction transaction = mTransactionManager.createLoadTransaction( + contextHubId, nanoAppBinary, transactionCallback); + addTransaction(transaction); + } + + /** + * Unloads a nanoapp from the specified Context Hub. + * + * @param contextHubId the ID of the hub to unload the nanoapp + * @param transactionCallback the client-facing transaction callback interface + * @param nanoAppId the ID of the nanoapp to unload + * + * @throws RemoteException + */ + @Override + public void unloadNanoAppFromHub( + int contextHubId, IContextHubTransactionCallback transactionCallback, long nanoAppId) + throws RemoteException { + checkPermissions(); + if (!checkHalProxyAndContextHubId( + contextHubId, transactionCallback, ContextHubTransaction.TYPE_UNLOAD_NANOAPP)) { + return; + } + + ContextHubServiceTransaction transaction = mTransactionManager.createUnloadTransaction( + contextHubId, nanoAppId, transactionCallback); + addTransaction(transaction); + } + + /** + * Queries for a list of nanoapps from the specified Context hub. + * + * @param contextHubId the ID of the hub to query + * @param transactionCallback the client-facing transaction callback interface + * + * @throws RemoteException + */ + @Override + public void queryNanoApps(int contextHubId, IContextHubTransactionCallback transactionCallback) + throws RemoteException { + checkPermissions(); + if (!checkHalProxyAndContextHubId( + contextHubId, transactionCallback, ContextHubTransaction.TYPE_QUERY_NANOAPPS)) { + return; + } + + ContextHubServiceTransaction transaction = + mTransactionManager.createQueryTransaction(contextHubId, transactionCallback); + addTransaction(transaction); + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; @@ -797,6 +873,42 @@ public class ContextHubService extends IContextHubService.Stub { return 0; } + /** + * Validates the HAL proxy state and context hub ID to see if we can start the transaction. + * + * @param contextHubId the ID of the hub to start the transaction + * @param callback the client transaction callback interface + * @param transactionType the type of the transaction + * + * @return {@code true} if mContextHubProxy and contextHubId is valid, {@code false} otherwise + */ + private boolean checkHalProxyAndContextHubId( + int contextHubId, IContextHubTransactionCallback callback, + @ContextHubTransaction.Type int transactionType) { + if (mContextHubProxy == null) { + try { + callback.onTransactionComplete( + ContextHubTransaction.TRANSACTION_FAILED_HAL_UNAVAILABLE); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException while calling onTransactionComplete", e); + } + return false; + } + if (!isValidContextHubId(contextHubId)) { + Log.e(TAG, "Cannot start " + + ContextHubTransaction.typeToString(transactionType, false /* upperCase */) + + " transaction for invalid hub ID " + contextHubId); + try { + callback.onTransactionComplete(ContextHubTransaction.TRANSACTION_FAILED_BAD_PARAMS); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException while calling onTransactionComplete", e); + } + return false; + } + + return true; + } + private int addAppInstance(int hubHandle, int appInstanceHandle, long appId, int appVersion) { // App Id encodes vendor & version NanoAppInstanceInfo appInfo = new NanoAppInstanceInfo(); diff --git a/services/core/java/com/android/server/location/ContextHubServiceTransaction.java b/services/core/java/com/android/server/location/ContextHubServiceTransaction.java index a543dafc1ed1..ce92f722e2d2 100644 --- a/services/core/java/com/android/server/location/ContextHubServiceTransaction.java +++ b/services/core/java/com/android/server/location/ContextHubServiceTransaction.java @@ -126,28 +126,9 @@ import java.util.concurrent.TimeUnit; return mIsComplete; } - /** - * @return the human-readable string of this transaction's type - */ - private String getTransactionTypeString() { - switch (mTransactionType) { - case ContextHubTransaction.TYPE_LOAD_NANOAPP: - return "Load"; - case ContextHubTransaction.TYPE_UNLOAD_NANOAPP: - return "Unload"; - case ContextHubTransaction.TYPE_ENABLE_NANOAPP: - return "Enable"; - case ContextHubTransaction.TYPE_DISABLE_NANOAPP: - return "Disable"; - case ContextHubTransaction.TYPE_QUERY_NANOAPPS: - return "Query"; - default: - return "Unknown"; - } - } - @Override public String toString() { - return getTransactionTypeString() + " transaction (ID = " + mTransactionId + ")"; + return ContextHubTransaction.typeToString(mTransactionType, true /* upperCase */) + + " transaction (ID = " + mTransactionId + ")"; } } diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGenerator.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGenerator.java new file mode 100644 index 000000000000..40c788997ba5 --- /dev/null +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGenerator.java @@ -0,0 +1,133 @@ +/* + * 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.locksettings.recoverablekeystore; + +import android.security.keystore.AndroidKeyStoreSecretKey; +import android.security.keystore.KeyProperties; +import android.security.keystore.KeyProtection; +import android.util.Log; + +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableEntryException; + +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.security.auth.DestroyFailedException; + +/** + * Generates keys and stores them both in AndroidKeyStore and on disk, in wrapped form. + * + * <p>Generates 256-bit AES keys, which can be used for encrypt / decrypt with AES/GCM/NoPadding. + * They are synced to disk wrapped by a platform key. This allows them to be exported to a remote + * service. + * + * @hide + */ +public class RecoverableKeyGenerator { + private static final String TAG = "RecoverableKeyGenerator"; + private static final String KEY_GENERATOR_ALGORITHM = "AES"; + private static final int KEY_SIZE_BITS = 256; + + /** + * A new {@link RecoverableKeyGenerator} instance. + * + * @param platformKey Secret key used to wrap generated keys before persisting to disk. + * @param recoverableKeyStorage Class that manages persisting wrapped keys to disk. + * @throws NoSuchAlgorithmException if "AES" key generation or "AES/GCM/NoPadding" cipher is + * unavailable. Should never happen. + * + * @hide + */ + public static RecoverableKeyGenerator newInstance( + AndroidKeyStoreSecretKey platformKey, RecoverableKeyStorage recoverableKeyStorage) + throws NoSuchAlgorithmException { + // NB: This cannot use AndroidKeyStore as the provider, as we need access to the raw key + // material, so that it can be synced to disk in encrypted form. + KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_GENERATOR_ALGORITHM); + return new RecoverableKeyGenerator(keyGenerator, platformKey, recoverableKeyStorage); + } + + private final KeyGenerator mKeyGenerator; + private final RecoverableKeyStorage mRecoverableKeyStorage; + private final AndroidKeyStoreSecretKey mPlatformKey; + + private RecoverableKeyGenerator( + KeyGenerator keyGenerator, + AndroidKeyStoreSecretKey platformKey, + RecoverableKeyStorage recoverableKeyStorage) { + mKeyGenerator = keyGenerator; + mRecoverableKeyStorage = recoverableKeyStorage; + mPlatformKey = platformKey; + } + + /** + * Generates a 256-bit AES key with the given alias. + * + * <p>Stores in the AndroidKeyStore, as well as persisting in wrapped form to disk. It is + * persisted to disk so that it can be synced remotely, and then recovered on another device. + * The generated key allows encrypt/decrypt only using AES/GCM/NoPadding. + * + * <p>The key handle returned to the caller is a reference to the AndroidKeyStore key, + * meaning that the caller is never able to access the raw, unencrypted key. + * + * @param alias The alias by which the key will be known in AndroidKeyStore. + * @throws InvalidKeyException if the platform key cannot be used to wrap keys. + * @throws IOException if there was an issue writing the wrapped key to the wrapped key store. + * @throws UnrecoverableEntryException if could not retrieve key after putting it in + * AndroidKeyStore. This should not happen. + * @return A handle to the AndroidKeyStore key. + * + * @hide + */ + public SecretKey generateAndStoreKey(String alias) throws KeyStoreException, + InvalidKeyException, IOException, UnrecoverableEntryException { + mKeyGenerator.init(KEY_SIZE_BITS); + SecretKey key = mKeyGenerator.generateKey(); + + mRecoverableKeyStorage.importIntoAndroidKeyStore( + alias, + key, + new KeyProtection.Builder( + KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) + .setBlockModes(KeyProperties.BLOCK_MODE_GCM) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) + .build()); + WrappedKey wrappedKey = WrappedKey.fromSecretKey(mPlatformKey, key); + + try { + // Keep raw key material in memory for minimum possible time. + key.destroy(); + } catch (DestroyFailedException e) { + Log.w(TAG, "Could not destroy SecretKey."); + } + + mRecoverableKeyStorage.persistToDisk(alias, wrappedKey); + + try { + // Reload from the keystore, so that the caller is only provided with the handle of the + // key, not the raw key material. + return mRecoverableKeyStorage.loadFromAndroidKeyStore(alias); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException( + "Impossible: NoSuchAlgorithmException when attempting to retrieve a key " + + "that has only just been stored in AndroidKeyStore.", e); + } + } +} diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStorage.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStorage.java new file mode 100644 index 000000000000..cd85a97c3522 --- /dev/null +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStorage.java @@ -0,0 +1,71 @@ +/* + * 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.locksettings.recoverablekeystore; + +import android.security.keystore.KeyProtection; + +import java.io.IOException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableEntryException; + +import javax.crypto.SecretKey; + +/** + * Stores wrapped keys to disk, so they can be synced on the next screen unlock event. + * + * @hide + */ +public interface RecoverableKeyStorage { + + /** + * Writes {@code wrappedKey} to disk, keyed by the application's uid and the {@code alias}. + * + * @throws IOException if an error occurred writing to disk. + * + * @hide + */ + void persistToDisk(String alias, WrappedKey wrappedKey) throws IOException; + + /** + * Imports {@code key} into AndroidKeyStore, keyed by the application's uid and + * the {@code alias}. + * + * @param alias The alias of the key. + * @param key The key. + * @param keyProtection Protection params denoting what the key can be used for. (e.g., what + * Cipher modes, whether for encrpyt/decrypt or signing, etc.) + * @throws KeyStoreException if an error occurred loading the key into the AndroidKeyStore. + * + * @hide + */ + void importIntoAndroidKeyStore(String alias, SecretKey key, KeyProtection keyProtection) throws + KeyStoreException; + + /** + * Loads a key handle from AndroidKeyStore. + * + * @param alias Alias of the key to load. + * @return The key handle. + * @throws KeyStoreException if an error occurred loading the key from AndroidKeyStore. + * + * @hide + */ + SecretKey loadFromAndroidKeyStore(String alias) throws KeyStoreException, + NoSuchAlgorithmException, + UnrecoverableEntryException; +} diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStorageImpl.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStorageImpl.java new file mode 100644 index 000000000000..4e0751b2ad95 --- /dev/null +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStorageImpl.java @@ -0,0 +1,110 @@ +/* + * 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.locksettings.recoverablekeystore; + +import android.security.keystore.KeyProtection; + +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableEntryException; +import java.security.cert.CertificateException; + +import javax.crypto.SecretKey; + +/** + * Implementation of {@link RecoverableKeyStorage}. + * + * <p>Persists wrapped keys to disk, and loads raw keys into AndroidKeyStore. + * + * @hide + */ +public class RecoverableKeyStorageImpl implements RecoverableKeyStorage { + private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore"; + + private final KeyStore mKeyStore; + + /** + * A new instance. + * + * @throws KeyStoreException if unable to load AndroidKeyStore. + * + * @hide + */ + public static RecoverableKeyStorageImpl newInstance() throws KeyStoreException { + KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER); + try { + keyStore.load(/*param=*/ null); + } catch (CertificateException | IOException | NoSuchAlgorithmException e) { + // Should never happen. + throw new KeyStoreException("Unable to load keystore.", e); + } + return new RecoverableKeyStorageImpl(keyStore); + } + + private RecoverableKeyStorageImpl(KeyStore keyStore) { + mKeyStore = keyStore; + } + + /** + * Writes {@code wrappedKey} to disk, keyed by the application's uid and the {@code alias}. + * + * @throws IOException if an error occurred writing to disk. + * + * @hide + */ + @Override + public void persistToDisk(String alias, WrappedKey wrappedKey) throws IOException { + // TODO(robertberry) Add implementation. + throw new UnsupportedOperationException(); + } + + /** + * Imports {@code key} into AndroidKeyStore, keyed by the application's uid and the + * {@code alias}. + * + * @param alias The alias of the key. + * @param key The key. + * @param keyProtection Protection params denoting what the key can be used for. (e.g., what + * Cipher modes, whether for encrpyt/decrypt or signing, etc.) + * @throws KeyStoreException if an error occurred loading the key into the AndroidKeyStore. + * + * @hide + */ + @Override + public void importIntoAndroidKeyStore(String alias, SecretKey key, KeyProtection keyProtection) + throws KeyStoreException { + mKeyStore.setEntry(alias, new KeyStore.SecretKeyEntry(key), keyProtection); + } + + /** + * Loads a key handle from AndroidKeyStore. + * + * @param alias Alias of the key to load. + * @return The key handle. + * @throws KeyStoreException if an error occurred loading the key from AndroidKeyStore. + * + * @hide + */ + @Override + public SecretKey loadFromAndroidKeyStore(String alias) + throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException { + return ((KeyStore.SecretKeyEntry) mKeyStore.getEntry(alias, /*protParam=*/ null)) + .getSecretKey(); + } +} diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/WrappedKey.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/WrappedKey.java new file mode 100644 index 000000000000..c97c66ef9016 --- /dev/null +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/WrappedKey.java @@ -0,0 +1,115 @@ +/* + * 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.locksettings.recoverablekeystore; + +import java.security.InvalidKeyException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; + +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; + +/** + * A {@link javax.crypto.SecretKey} wrapped with AES/GCM/NoPadding. + * + * @hide + */ +public class WrappedKey { + private static final String KEY_WRAP_CIPHER_ALGORITHM = "AES/GCM/NoPadding"; + + private final byte[] mNonce; + private final byte[] mKeyMaterial; + + /** + * Returns a wrapped form of {@code key}, using {@code wrappingKey} to encrypt the key material. + * + * @throws InvalidKeyException if {@code wrappingKey} cannot be used to encrypt {@code key}, or + * if {@code key} does not expose its key material. See + * {@link android.security.keystore.AndroidKeyStoreKey} for an example of a key that does + * not expose its key material. + */ + public static WrappedKey fromSecretKey( + SecretKey wrappingKey, SecretKey key) throws InvalidKeyException, KeyStoreException { + if (key.getEncoded() == null) { + throw new InvalidKeyException( + "key does not expose encoded material. It cannot be wrapped."); + } + + Cipher cipher; + try { + cipher = Cipher.getInstance(KEY_WRAP_CIPHER_ALGORITHM); + } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { + throw new RuntimeException( + "Android does not support AES/GCM/NoPadding. This should never happen."); + } + + cipher.init(Cipher.WRAP_MODE, wrappingKey); + byte[] encryptedKeyMaterial; + try { + encryptedKeyMaterial = cipher.wrap(key); + } catch (IllegalBlockSizeException e) { + Throwable cause = e.getCause(); + if (cause instanceof KeyStoreException) { + // If AndroidKeyStore encounters any error here, it throws IllegalBlockSizeException + // with KeyStoreException as the cause. This is due to there being no better option + // here, as the Cipher#wrap only checked throws InvalidKeyException or + // IllegalBlockSizeException. If this is the case, we want to propagate it to the + // caller, so rethrow the cause. + throw (KeyStoreException) cause; + } else { + throw new RuntimeException( + "IllegalBlockSizeException should not be thrown by AES/GCM/NoPadding mode.", + e); + } + } + + return new WrappedKey(/*mNonce=*/ cipher.getIV(), /*mKeyMaterial=*/ encryptedKeyMaterial); + } + + /** + * A new instance. + * + * @param nonce The nonce with which the key material was encrypted. + * @param keyMaterial The encrypted bytes of the key material. + * + * @hide + */ + public WrappedKey(byte[] nonce, byte[] keyMaterial) { + mNonce = nonce; + mKeyMaterial = keyMaterial; + } + + /** + * Returns the nonce with which the key material was encrypted. + * + * @hide + */ + public byte[] getNonce() { + return mNonce; + } + + /** + * Returns the encrypted key material. + * + * @hide + */ + public byte[] getKeyMaterial() { + return mKeyMaterial; + } +} diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index 2940a6e3fc8d..2041de64c8fb 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -370,10 +370,10 @@ public final class OverlayManagerService extends SystemService { false); if (pi != null) { mPackageManager.cachePackageInfo(packageName, userId, pi); - if (!isOverlayPackage(pi)) { - mImpl.onTargetPackageAdded(packageName, userId); - } else { + if (pi.isOverlayPackage()) { mImpl.onOverlayPackageAdded(packageName, userId); + } else { + mImpl.onTargetPackageAdded(packageName, userId); } } } @@ -388,10 +388,10 @@ public final class OverlayManagerService extends SystemService { false); if (pi != null) { mPackageManager.cachePackageInfo(packageName, userId, pi); - if (!isOverlayPackage(pi)) { - mImpl.onTargetPackageChanged(packageName, userId); - } else { + if (pi.isOverlayPackage()) { mImpl.onOverlayPackageChanged(packageName, userId); + } else { + mImpl.onTargetPackageChanged(packageName, userId); } } } @@ -404,10 +404,10 @@ public final class OverlayManagerService extends SystemService { synchronized (mLock) { mPackageManager.forgetPackageInfo(packageName, userId); final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId); - if (oi == null) { - mImpl.onTargetPackageUpgrading(packageName, userId); - } else { + if (oi != null) { mImpl.onOverlayPackageUpgrading(packageName, userId); + } else { + mImpl.onTargetPackageUpgrading(packageName, userId); } } } @@ -421,10 +421,10 @@ public final class OverlayManagerService extends SystemService { false); if (pi != null) { mPackageManager.cachePackageInfo(packageName, userId, pi); - if (!isOverlayPackage(pi)) { - mImpl.onTargetPackageUpgraded(packageName, userId); - } else { + if (pi.isOverlayPackage()) { mImpl.onOverlayPackageUpgraded(packageName, userId); + } else { + mImpl.onTargetPackageUpgraded(packageName, userId); } } } @@ -437,10 +437,10 @@ public final class OverlayManagerService extends SystemService { synchronized (mLock) { mPackageManager.forgetPackageInfo(packageName, userId); final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId); - if (oi == null) { - mImpl.onTargetPackageRemoved(packageName, userId); - } else { + if (oi != null) { mImpl.onOverlayPackageRemoved(packageName, userId); + } else { + mImpl.onTargetPackageRemoved(packageName, userId); } } } @@ -668,10 +668,6 @@ public final class OverlayManagerService extends SystemService { } }; - private boolean isOverlayPackage(@NonNull final PackageInfo pi) { - return pi != null && pi.overlayTarget != null; - } - private final class OverlayChangeListener implements OverlayManagerServiceImpl.OverlayChangeListener { @Override diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index db6e9749535b..253d4f5b22bb 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -102,11 +102,11 @@ final class OverlayManagerServiceImpl { mSettings.init(overlayPackage.packageName, newUserId, overlayPackage.overlayTarget, overlayPackage.applicationInfo.getBaseCodePath(), - overlayPackage.isStaticOverlay, overlayPackage.overlayPriority); + overlayPackage.isStaticOverlayPackage(), overlayPackage.overlayPriority); if (oi == null) { // This overlay does not exist in our settings. - if (overlayPackage.isStaticOverlay || + if (overlayPackage.isStaticOverlayPackage() || mDefaultOverlays.contains(overlayPackage.packageName)) { // Enable this overlay by default. if (DEBUG) { @@ -255,8 +255,8 @@ final class OverlayManagerServiceImpl { mPackageManager.getPackageInfo(overlayPackage.overlayTarget, userId); mSettings.init(packageName, userId, overlayPackage.overlayTarget, - overlayPackage.applicationInfo.getBaseCodePath(), overlayPackage.isStaticOverlay, - overlayPackage.overlayPriority); + overlayPackage.applicationInfo.getBaseCodePath(), + overlayPackage.isStaticOverlayPackage(), overlayPackage.overlayPriority); try { if (updateState(targetPackage, overlayPackage, userId)) { mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId); @@ -313,7 +313,7 @@ final class OverlayManagerServiceImpl { } // Ignore static overlays. - if (overlayPackage.isStaticOverlay) { + if (overlayPackage.isStaticOverlayPackage()) { return false; } @@ -363,7 +363,7 @@ final class OverlayManagerServiceImpl { continue; } - if (disabledOverlayPackageInfo.isStaticOverlay) { + if (disabledOverlayPackageInfo.isStaticOverlayPackage()) { // Don't touch static overlays. continue; } @@ -388,7 +388,7 @@ final class OverlayManagerServiceImpl { private boolean isPackageUpdatableOverlay(@NonNull final String packageName, final int userId) { final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId); - if (overlayPackage == null || overlayPackage.isStaticOverlay) { + if (overlayPackage == null || overlayPackage.isStaticOverlayPackage()) { return false; } return true; @@ -483,7 +483,8 @@ final class OverlayManagerServiceImpl { throws OverlayManagerSettings.BadKeyException { // Static RROs targeting to "android", ie framework-res.apk, are handled by native layers. if (targetPackage != null && - !("android".equals(targetPackage.packageName) && overlayPackage.isStaticOverlay)) { + !("android".equals(targetPackage.packageName) + && overlayPackage.isStaticOverlayPackage())) { mIdmapManager.createIdmap(targetPackage, overlayPackage, userId); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index e0f3ec7453a9..f106391f5916 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -47,6 +47,7 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR; import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK; import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; import static android.content.pm.PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY; +import static android.content.pm.PackageManager.INSTALL_FAILED_NEWER_SDK; import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED; import static android.content.pm.PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE; import static android.content.pm.PackageManager.INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE; @@ -12884,14 +12885,13 @@ public class PackageManagerService extends IPackageManager.Stub if (getInstantAppPackageName(Binder.getCallingUid()) != null) { return null; } - // writer - synchronized (mPackages) { - if (!isExternalMediaAvailable()) { + if (!isExternalMediaAvailable()) { // If the external storage is no longer mounted at this point, // the caller may not have been able to delete all of this // packages files and can not delete any more. Bail. - return null; - } + return null; + } + synchronized (mPackages) { final ArrayList<PackageCleanItem> pkgs = mSettings.mPackagesToBeCleaned; if (lastPackage != null) { pkgs.remove(lastPackage); @@ -16284,6 +16284,16 @@ public class PackageManagerService extends IPackageManager.Stub Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } + // App targetSdkVersion is below min supported version + if (!forceSdk && pkg.applicationInfo.isTargetingDeprecatedSdkVersion()) { + Slog.w(TAG, "App " + pkg.packageName + " targets deprecated sdk"); + + res.setError(INSTALL_FAILED_NEWER_SDK, + "App is targeting deprecated sdk (targetSdkVersion should be at least " + + Build.VERSION.MIN_SUPPORTED_TARGET_SDK_INT + ")."); + return; + } + // Instant apps must have target SDK >= O and have targetSanboxVersion >= 2 if (instantApp && pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) { Slog.w(TAG, "Instant app package " + pkg.packageName + " does not target O"); @@ -16421,6 +16431,13 @@ public class PackageManagerService extends IPackageManager.Stub + " target SDK " + oldTargetSdk + " does."); return; } + // Prevent persistent apps from being updated + if ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0) { + res.setError(PackageManager.INSTALL_FAILED_INVALID_APK, + "Package " + oldPackage.packageName + " is a persistent app. " + + "Persistent apps are not updateable."); + return; + } // Prevent apps from downgrading their targetSandbox. final int oldTargetSandbox = oldPackage.applicationInfo.targetSandboxVersion; final int newTargetSandbox = pkg.applicationInfo.targetSandboxVersion; diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index a7cced75bfd6..2d82c469592e 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -1374,7 +1374,7 @@ class PackageManagerShellCommand extends ShellCommand { } ClearDataObserver obs = new ClearDataObserver(); - ActivityManager.getService().clearApplicationUserData(pkg, obs, userId); + ActivityManager.getService().clearApplicationUserData(pkg, false, obs, userId); synchronized (obs) { while (!obs.finished) { try { diff --git a/services/core/java/com/android/server/pm/ShortcutNonPersistentUser.java b/services/core/java/com/android/server/pm/ShortcutNonPersistentUser.java new file mode 100644 index 000000000000..7f6f684e0b68 --- /dev/null +++ b/services/core/java/com/android/server/pm/ShortcutNonPersistentUser.java @@ -0,0 +1,98 @@ +/* + * 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.pm; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.util.ArrayMap; +import android.util.ArraySet; + +import com.android.server.pm.ShortcutService.DumpFilter; + +import java.io.PrintWriter; + +/** + * This class holds per-user information for {@link ShortcutService} that doesn't have to be + * persisted and is kept in-memory. + * + * The access to it must be guarded with the shortcut manager lock. + */ +public class ShortcutNonPersistentUser { + private final ShortcutService mService; + + private final int mUserId; + + /** + * Keep track of additional packages that other parts of the system have said are + * allowed to access shortcuts. The key is the part of the system it came from, + * the value is the package name that has access. We don't persist these because + * at boot all relevant system services will push this data back to us they do their + * normal evaluation of the state of the world. + */ + private final ArrayMap<String, String> mHostPackages = new ArrayMap<>(); + + /** + * Set of package name values from above. + */ + private final ArraySet<String> mHostPackageSet = new ArraySet<>(); + + public ShortcutNonPersistentUser(ShortcutService service, int userId) { + mService = service; + mUserId = userId; + } + + public int getUserId() { + return mUserId; + } + + public void setShortcutHostPackage(@NonNull String type, @Nullable String packageName) { + if (packageName != null) { + mHostPackages.put(type, packageName); + } else { + mHostPackages.remove(type); + } + + mHostPackageSet.clear(); + for (int i = 0; i < mHostPackages.size(); i++) { + mHostPackageSet.add(mHostPackages.valueAt(i)); + } + } + + public boolean hasHostPackage(@NonNull String packageName) { + return mHostPackageSet.contains(packageName); + } + + public void dump(@NonNull PrintWriter pw, @NonNull String prefix, DumpFilter filter) { + if (filter.shouldDumpDetails()) { + if (mHostPackages.size() > 0) { + pw.print(prefix); + pw.print("Non-persistent: user ID:"); + pw.println(mUserId); + + pw.print(prefix); + pw.println(" Host packages:"); + for (int i = 0; i < mHostPackages.size(); i++) { + pw.print(prefix); + pw.print(" "); + pw.print(mHostPackages.keyAt(i)); + pw.print(": "); + pw.println(mHostPackages.valueAt(i)); + } + pw.println(); + } + } + } +} diff --git a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java index b14e9c99b138..3d37229642d1 100644 --- a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java +++ b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java @@ -148,7 +148,7 @@ class ShortcutPackageInfo { if (!anyVersionOkay && (currentPackage.getLongVersionCode() < mBackupSourceVersionCode)) { Slog.w(TAG, String.format( "Can't restore: package current version %d < backed up version %d", - currentPackage.versionCode, mBackupSourceVersionCode)); + currentPackage.getLongVersionCode(), mBackupSourceVersionCode)); return ShortcutInfo.DISABLED_REASON_VERSION_LOWER; } return ShortcutInfo.DISABLED_REASON_NOT_DISABLED; diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index ee2f3742c811..065eafd9156a 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -280,6 +280,13 @@ public class ShortcutService extends IShortcutService.Stub { private final SparseArray<ShortcutUser> mUsers = new SparseArray<>(); /** + * User ID -> ShortcutNonPersistentUser + */ + @GuardedBy("mLock") + private final SparseArray<ShortcutNonPersistentUser> mShortcutNonPersistentUsers = + new SparseArray<>(); + + /** * Max number of dynamic + manifest shortcuts that each application can have at a time. */ private int mMaxShortcuts; @@ -330,7 +337,10 @@ public class ShortcutService extends IShortcutService.Stub { | PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.MATCH_UNINSTALLED_PACKAGES; - @GuardedBy("mLock") + /** + * Note we use a fine-grained lock for {@link #mUnlockedUsers} due to b/64303666. + */ + @GuardedBy("mUnlockedUsers") final SparseBooleanArray mUnlockedUsers = new SparseBooleanArray(); // Stats @@ -600,7 +610,7 @@ public class ShortcutService extends IShortcutService.Stub { if (DEBUG) { Slog.d(TAG, "handleUnlockUser: user=" + userId); } - synchronized (mLock) { + synchronized (mUnlockedUsers) { mUnlockedUsers.put(userId, true); } @@ -628,7 +638,9 @@ public class ShortcutService extends IShortcutService.Stub { synchronized (mLock) { unloadUserLocked(userId); - mUnlockedUsers.put(userId, false); + synchronized (mUnlockedUsers) { + mUnlockedUsers.put(userId, false); + } } } @@ -1149,9 +1161,12 @@ public class ShortcutService extends IShortcutService.Stub { // Requires mLock held, but "Locked" prefix would look weired so we just say "L". protected boolean isUserUnlockedL(@UserIdInt int userId) { // First, check the local copy. - if (mUnlockedUsers.get(userId)) { - return true; + synchronized (mUnlockedUsers) { + if (mUnlockedUsers.get(userId)) { + return true; + } } + // If the local copy says the user is locked, check with AM for the actual state, since // the user might just have been unlocked. // Note we just don't use isUserUnlockingOrUnlocked() here, because it'll return false @@ -1199,6 +1214,18 @@ public class ShortcutService extends IShortcutService.Stub { return userPackages; } + /** Return the non-persistent per-user state. */ + @GuardedBy("mLock") + @NonNull + ShortcutNonPersistentUser getNonPersistentUserLocked(@UserIdInt int userId) { + ShortcutNonPersistentUser ret = mShortcutNonPersistentUsers.get(userId); + if (ret == null) { + ret = new ShortcutNonPersistentUser(this, userId); + mShortcutNonPersistentUsers.put(userId, ret); + } + return ret; + } + void forEachLoadedUserLocked(@NonNull Consumer<ShortcutUser> c) { for (int i = mUsers.size() - 1; i >= 0; i--) { c.accept(mUsers.valueAt(i)); @@ -2251,7 +2278,7 @@ public class ShortcutService extends IShortcutService.Stub { return true; } synchronized (mLock) { - return getUserShortcutsLocked(userId).hasHostPackage(callingPackage); + return getNonPersistentUserLocked(userId).hasHostPackage(callingPackage); } } @@ -2375,10 +2402,7 @@ public class ShortcutService extends IShortcutService.Stub { public void setShortcutHostPackage(@NonNull String type, @Nullable String packageName, int userId) { synchronized (mLock) { - throwIfUserLockedL(userId); - - final ShortcutUser user = getUserShortcutsLocked(userId); - user.setShortcutHostPackage(type, packageName); + getNonPersistentUserLocked(userId).setShortcutHostPackage(type, packageName); } } @@ -3836,6 +3860,14 @@ public class ShortcutService extends IShortcutService.Stub { pw.println(); } } + + for (int i = 0; i < mShortcutNonPersistentUsers.size(); i++) { + final ShortcutNonPersistentUser user = mShortcutNonPersistentUsers.valueAt(i); + if (filter.isUserMatch(user.getUserId())) { + user.dump(pw, " ", filter); + pw.println(); + } + } } } diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java index 1efd765b18fa..b7247df3b2a1 100644 --- a/services/core/java/com/android/server/pm/ShortcutUser.java +++ b/services/core/java/com/android/server/pm/ShortcutUser.java @@ -124,20 +124,6 @@ class ShortcutUser { /** In-memory-cached default launcher. */ private ComponentName mCachedLauncher; - /** - * Keep track of additional packages that other parts of the system have said are - * allowed to access shortcuts. The key is the part of the system it came from, - * the value is the package name that has access. We don't persist these because - * at boot all relevant system services will push this data back to us they do their - * normal evaluation of the state of the world. - */ - private final ArrayMap<String, String> mHostPackages = new ArrayMap<>(); - - /** - * Set of package name values from above. - */ - private final ArraySet<String> mHostPackageSet = new ArraySet<>(); - private String mKnownLocales; private long mLastAppScanTime; @@ -482,23 +468,6 @@ class ShortcutUser { return mCachedLauncher; } - public void setShortcutHostPackage(@NonNull String type, @Nullable String packageName) { - if (packageName != null) { - mHostPackages.put(type, packageName); - } else { - mHostPackages.remove(type); - } - - mHostPackageSet.clear(); - for (int i = 0; i < mHostPackages.size(); i++) { - mHostPackageSet.add(mHostPackages.valueAt(i)); - } - } - - public boolean hasHostPackage(@NonNull String packageName) { - return mHostPackageSet.contains(packageName); - } - public void resetThrottling() { for (int i = mPackages.size() - 1; i >= 0; i--) { mPackages.valueAt(i).resetThrottling(); @@ -587,18 +556,6 @@ class ShortcutUser { pw.print("Last known launcher: "); pw.print(mLastKnownLauncher); pw.println(); - - if (mHostPackages.size() > 0) { - pw.print(prefix); - pw.println("Host packages:"); - for (int i = 0; i < mHostPackages.size(); i++) { - pw.print(prefix); - pw.print(" "); - pw.print(mHostPackages.keyAt(i)); - pw.print(": "); - pw.println(mHostPackages.valueAt(i)); - } - } } for (int i = 0; i < mLaunchers.size(); i++) { diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index dc481ca11c7b..03cd4f1d3269 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -3702,8 +3702,10 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public UserInfo createUserEvenWhenDisallowed(String name, int flags) { - UserInfo user = createUserInternalUnchecked(name, flags, UserHandle.USER_NULL, null); + public UserInfo createUserEvenWhenDisallowed(String name, int flags, + String[] disallowedPackages) { + UserInfo user = createUserInternalUnchecked(name, flags, UserHandle.USER_NULL, + disallowedPackages); // Keep this in sync with UserManager.createUser if (user != null && !user.isAdmin() && !user.isDemo()) { setUserRestriction(UserManager.DISALLOW_SMS, true, user.id); diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 61591bbef08d..5f03dd262fa4 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -321,11 +321,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final int LONG_PRESS_BACK_NOTHING = 0; static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1; - // Number of presses needed before we induce panic press behavior on the back button - static final int PANIC_PRESS_BACK_COUNT = 4; - static final int PANIC_PRESS_BACK_NOTHING = 0; - static final int PANIC_PRESS_BACK_HOME = 1; - // These need to match the documentation/constant in // core/res/res/values/config.xml static final int LONG_PRESS_HOME_NOTHING = 0; @@ -520,7 +515,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { volatile boolean mBackKeyHandled; volatile boolean mBeganFromNonInteractive; volatile int mPowerKeyPressCounter; - volatile int mBackKeyPressCounter; volatile boolean mEndCallKeyHandled; volatile boolean mCameraGestureTriggeredDuringGoingToSleep; volatile boolean mGoingToSleep; @@ -582,7 +576,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mDoublePressOnPowerBehavior; int mTriplePressOnPowerBehavior; int mLongPressOnBackBehavior; - int mPanicPressOnBackBehavior; int mShortPressOnSleepBehavior; int mShortPressOnWindowBehavior; volatile boolean mAwake; @@ -800,16 +793,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { private static final int MSG_SHOW_PICTURE_IN_PICTURE_MENU = 17; private static final int MSG_BACK_LONG_PRESS = 18; private static final int MSG_DISPOSE_INPUT_CONSUMER = 19; - private static final int MSG_BACK_DELAYED_PRESS = 20; - private static final int MSG_ACCESSIBILITY_SHORTCUT = 21; - private static final int MSG_BUGREPORT_TV = 22; - private static final int MSG_ACCESSIBILITY_TV = 23; - private static final int MSG_DISPATCH_BACK_KEY_TO_AUTOFILL = 24; - private static final int MSG_SYSTEM_KEY_PRESS = 25; - private static final int MSG_HANDLE_ALL_APPS = 26; - private static final int MSG_LAUNCH_ASSIST = 27; - private static final int MSG_LAUNCH_ASSIST_LONG_PRESS = 28; - private static final int MSG_POWER_VERY_LONG_PRESS = 29; + private static final int MSG_ACCESSIBILITY_SHORTCUT = 20; + private static final int MSG_BUGREPORT_TV = 21; + private static final int MSG_ACCESSIBILITY_TV = 22; + private static final int MSG_DISPATCH_BACK_KEY_TO_AUTOFILL = 23; + private static final int MSG_SYSTEM_KEY_PRESS = 24; + private static final int MSG_HANDLE_ALL_APPS = 25; + private static final int MSG_LAUNCH_ASSIST = 26; + private static final int MSG_LAUNCH_ASSIST_LONG_PRESS = 27; + private static final int MSG_POWER_VERY_LONG_PRESS = 28; private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0; private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1; @@ -887,15 +879,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { break; case MSG_BACK_LONG_PRESS: backLongPress(); - finishBackKeyPress(); break; case MSG_DISPOSE_INPUT_CONSUMER: disposeInputConsumer((InputConsumer) msg.obj); break; - case MSG_BACK_DELAYED_PRESS: - backMultiPressAction(msg.arg1); - finishBackKeyPress(); - break; case MSG_ACCESSIBILITY_SHORTCUT: accessibilityShortcutActivated(); break; @@ -1181,14 +1168,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Reset back key state for long press mBackKeyHandled = false; - // Cancel multi-press detection timeout. - if (hasPanicPressOnBackBehavior()) { - if (mBackKeyPressCounter != 0 - && mBackKeyPressCounter < PANIC_PRESS_BACK_COUNT) { - mHandler.removeMessages(MSG_BACK_DELAYED_PRESS); - } - } - if (hasLongPressOnBackBehavior()) { Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS); msg.setAsynchronous(true); @@ -1202,21 +1181,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Cache handled state boolean handled = mBackKeyHandled; - if (hasPanicPressOnBackBehavior()) { - // Check for back key panic press - ++mBackKeyPressCounter; - - final long eventTime = event.getDownTime(); - - if (mBackKeyPressCounter <= PANIC_PRESS_BACK_COUNT) { - // This could be a multi-press. Wait a little bit longer to confirm. - Message msg = mHandler.obtainMessage(MSG_BACK_DELAYED_PRESS, - mBackKeyPressCounter, 0, eventTime); - msg.setAsynchronous(true); - mHandler.sendMessageDelayed(msg, ViewConfiguration.getMultiPressTimeout()); - } - } - // Reset back long press state cancelPendingBackKeyAction(); @@ -1394,10 +1358,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - private void finishBackKeyPress() { - mBackKeyPressCounter = 0; - } - private void cancelPendingPowerKeyAction() { if (!mPowerKeyHandled) { mPowerKeyHandled = true; @@ -1415,18 +1375,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - private void backMultiPressAction(int count) { - if (count >= PANIC_PRESS_BACK_COUNT) { - switch (mPanicPressOnBackBehavior) { - case PANIC_PRESS_BACK_NOTHING: - break; - case PANIC_PRESS_BACK_HOME: - launchHomeFromHotKey(); - break; - } - } - } - private void powerPress(long eventTime, boolean interactive, int count) { if (mScreenOnEarly && !mScreenOnFully) { Slog.i(TAG, "Suppressed redundant power key press while " @@ -1642,10 +1590,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { return mLongPressOnBackBehavior != LONG_PRESS_BACK_NOTHING; } - private boolean hasPanicPressOnBackBehavior() { - return mPanicPressOnBackBehavior != PANIC_PRESS_BACK_NOTHING; - } - private void interceptScreenshotChord() { if (mScreenshotChordEnabled && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered @@ -2036,8 +1980,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mLongPressOnBackBehavior = mContext.getResources().getInteger( com.android.internal.R.integer.config_longPressOnBackBehavior); - mPanicPressOnBackBehavior = mContext.getResources().getInteger( - com.android.internal.R.integer.config_backPanicBehavior); mShortPressOnPowerBehavior = mContext.getResources().getInteger( com.android.internal.R.integer.config_shortPressOnPowerBehavior); @@ -8296,9 +8238,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print("mLongPressOnBackBehavior="); pw.println(longPressOnBackBehaviorToString(mLongPressOnBackBehavior)); pw.print(prefix); - pw.print("mPanicPressOnBackBehavior="); - pw.println(panicPressOnBackBehaviorToString(mPanicPressOnBackBehavior)); - pw.print(prefix); pw.print("mLongPressOnHomeBehavior="); pw.println(longPressOnHomeBehaviorToString(mLongPressOnHomeBehavior)); pw.print(prefix); @@ -8498,17 +8437,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - private static String panicPressOnBackBehaviorToString(int behavior) { - switch (behavior) { - case PANIC_PRESS_BACK_NOTHING: - return "PANIC_PRESS_BACK_NOTHING"; - case PANIC_PRESS_BACK_HOME: - return "PANIC_PRESS_BACK_HOME"; - default: - return Integer.toString(behavior); - } - } - private static String longPressOnHomeBehaviorToString(int behavior) { switch (behavior) { case LONG_PRESS_HOME_NOTHING: diff --git a/services/core/java/com/android/server/timezone/PackageStatusStorage.java b/services/core/java/com/android/server/timezone/PackageStatusStorage.java index 5601c91a78e7..251a27763fd2 100644 --- a/services/core/java/com/android/server/timezone/PackageStatusStorage.java +++ b/services/core/java/com/android/server/timezone/PackageStatusStorage.java @@ -82,12 +82,16 @@ final class PackageStatusStorage { PackageStatusStorage(File storageDir) { mPackageStatusFile = new AtomicFile(new File(storageDir, "package-status.xml")); + } + + /** + * Initialize any storage, as needed. + * + * @throws IOException if the storage could not be initialized + */ + void initialize() throws IOException { if (!mPackageStatusFile.getBaseFile().exists()) { - try { - insertInitialPackageStatus(); - } catch (IOException e) { - throw new IllegalStateException(e); - } + insertInitialPackageStatus(); } } @@ -342,13 +346,13 @@ final class PackageStatusStorage { } /** Only used during tests to force a known table state. */ - public void forceCheckStateForTests(int checkStatus, PackageVersions packageVersions) { + public void forceCheckStateForTests(int checkStatus, PackageVersions packageVersions) + throws IOException { synchronized (this) { try { - int optimisticLockId = getCurrentOptimisticLockId(); - writePackageStatusWithOptimisticLockCheck(optimisticLockId, optimisticLockId, - checkStatus, packageVersions); - } catch (IOException | ParseException e) { + final int initialOptimisticLockId = (int) System.currentTimeMillis(); + writePackageStatusLocked(checkStatus, initialOptimisticLockId, packageVersions); + } catch (IOException e) { throw new IllegalStateException(e); } } diff --git a/services/core/java/com/android/server/timezone/PackageTracker.java b/services/core/java/com/android/server/timezone/PackageTracker.java index 1c54320f25b8..0e8d8bc8e411 100644 --- a/services/core/java/com/android/server/timezone/PackageTracker.java +++ b/services/core/java/com/android/server/timezone/PackageTracker.java @@ -22,11 +22,15 @@ import android.app.timezone.RulesUpdaterContract; import android.content.Context; import android.content.pm.PackageManager; import android.os.Environment; +import android.os.FileUtils; +import android.os.SystemClock; import android.provider.TimeZoneRulesDataContract; import android.util.Slog; import java.io.File; +import java.io.IOException; import java.io.PrintWriter; +import java.time.Clock; /** * Monitors the installed applications associated with time zone updates. If the app packages are @@ -58,7 +62,7 @@ public class PackageTracker { private final IntentHelper mIntentHelper; private final ConfigHelper mConfigHelper; private final PackageStatusStorage mPackageStatusStorage; - private final ClockHelper mClockHelper; + private final Clock mElapsedRealtimeClock; // False if tracking is disabled. private boolean mTrackingEnabled; @@ -91,15 +95,11 @@ public class PackageTracker { /** Creates the {@link PackageTracker} for normal use. */ static PackageTracker create(Context context) { + Clock elapsedRealtimeClock = SystemClock.elapsedRealtimeClock(); PackageTrackerHelperImpl helperImpl = new PackageTrackerHelperImpl(context); - // TODO(nfuller): Switch to FileUtils.createDir() when available. http://b/31008728 - File storageDir = new File(Environment.getDataSystemDirectory(), "timezone"); - if (!storageDir.exists()) { - storageDir.mkdir(); - } - + File storageDir = FileUtils.createDir(Environment.getDataSystemDirectory(), "timezone"); return new PackageTracker( - helperImpl /* clock */, + elapsedRealtimeClock /* elapsedRealtimeClock */, helperImpl /* configHelper */, helperImpl /* packageManagerHelper */, new PackageStatusStorage(storageDir), @@ -107,10 +107,10 @@ public class PackageTracker { } // A constructor that can be used by tests to supply mocked / faked dependencies. - PackageTracker(ClockHelper clockHelper, ConfigHelper configHelper, + PackageTracker(Clock elapsedRealtimeClock, ConfigHelper configHelper, PackageManagerHelper packageManagerHelper, PackageStatusStorage packageStatusStorage, IntentHelper intentHelper) { - mClockHelper = clockHelper; + mElapsedRealtimeClock = elapsedRealtimeClock; mConfigHelper = configHelper; mPackageManagerHelper = packageManagerHelper; mPackageStatusStorage = packageStatusStorage; @@ -118,11 +118,11 @@ public class PackageTracker { } @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - protected synchronized void start() { + protected synchronized boolean start() { mTrackingEnabled = mConfigHelper.isTrackingEnabled(); if (!mTrackingEnabled) { Slog.i(TAG, "Time zone updater / data package tracking explicitly disabled."); - return; + return false; } mUpdateAppPackageName = mConfigHelper.getUpdateAppPackageName(); @@ -140,6 +140,14 @@ public class PackageTracker { mCheckTriggered = false; mCheckFailureCount = 0; + // Initialize the storage, as needed. + try { + mPackageStatusStorage.initialize(); + } catch (IOException e) { + Slog.w(TAG, "PackageTracker storage could not be initialized.", e); + return false; + } + // Initialize the intent helper. mIntentHelper.initialize(mUpdateAppPackageName, mDataAppPackageName, this); @@ -149,6 +157,7 @@ public class PackageTracker { mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis); Slog.i(TAG, "Time zone updater / data package tracking enabled"); + return true; } /** @@ -425,7 +434,7 @@ public class PackageTracker { } private void setCheckInProgress() { - mLastTriggerTimestamp = mClockHelper.currentTimestamp(); + mLastTriggerTimestamp = mElapsedRealtimeClock.millis(); } private void setCheckComplete() { @@ -441,7 +450,7 @@ public class PackageTracker { return false; } // Risk of overflow, but highly unlikely given the implementation and not problematic. - return mClockHelper.currentTimestamp() > mLastTriggerTimestamp + mCheckTimeAllowedMillis; + return mElapsedRealtimeClock.millis() > mLastTriggerTimestamp + mCheckTimeAllowedMillis; } private PackageVersions lookupInstalledPackageVersions() { diff --git a/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java b/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java index 6a330e6acf08..5f90be134b8d 100644 --- a/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java +++ b/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java @@ -25,7 +25,6 @@ import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.res.Resources; -import android.os.SystemClock; import android.os.UserHandle; import android.util.Slog; @@ -34,7 +33,7 @@ import java.util.List; /** * A single class that implements multiple helper interfaces for use by {@link PackageTracker}. */ -final class PackageTrackerHelperImpl implements ClockHelper, ConfigHelper, PackageManagerHelper { +final class PackageTrackerHelperImpl implements ConfigHelper, PackageManagerHelper { private static final String TAG = "PackageTrackerHelperImpl"; @@ -74,13 +73,6 @@ final class PackageTrackerHelperImpl implements ClockHelper, ConfigHelper, Packa } @Override - public long currentTimestamp() { - // Use of elapsedRealtime() because this is in-memory state and elapsedRealtime() shouldn't - // change if the system clock changes. - return SystemClock.elapsedRealtime(); - } - - @Override public long getInstalledPackageVersion(String packageName) throws PackageManager.NameNotFoundException { int flags = PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS; diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java index 52b49baf1073..30fc63c2a1b0 100644 --- a/services/core/java/com/android/server/timezone/RulesManagerService.java +++ b/services/core/java/com/android/server/timezone/RulesManagerService.java @@ -121,6 +121,7 @@ public final class RulesManagerService extends IRulesManager.Stub { } public void start() { + // Return value deliberately ignored: no action required on failure to start. mPackageTracker.start(); } diff --git a/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java b/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java index 0cf61c0c7c5a..e8a401e79235 100644 --- a/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java +++ b/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java @@ -16,6 +16,8 @@ package com.android.server.timezone; +import com.android.internal.util.DumpUtils; + import android.content.Context; import android.content.pm.PackageManager; import android.os.AsyncTask; @@ -46,15 +48,7 @@ final class RulesManagerServiceHelperImpl implements PermissionHelper, Executor @Override public boolean checkDumpPermission(String tag, PrintWriter pw) { - // TODO(nfuller): Switch to DumpUtils.checkDumpPermission() when it is available in AOSP. - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump LocationManagerService from from pid=" - + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid()); - return false; - } - return true; + return DumpUtils.checkDumpPermission(mContext, tag, pw); } @Override diff --git a/services/core/java/com/android/server/wallpaper/IWallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/IWallpaperManagerService.java new file mode 100644 index 000000000000..60b08dd3093c --- /dev/null +++ b/services/core/java/com/android/server/wallpaper/IWallpaperManagerService.java @@ -0,0 +1,35 @@ +/* + * 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.wallpaper; + +import android.app.IWallpaperManager; +import android.os.IBinder; + +/** + * Extended IWallpaperManager which can receive SystemService's lifetime events. + */ +interface IWallpaperManagerService extends IWallpaperManager, IBinder { + /** + * @see com.android.server.SystemService#onBootPhase(int) + */ + void onBootPhase(int phase); + + /** + * @see com.android.server.SystemService#onUnlockUser(int) + */ + void onUnlockUser(final int userId); +}
\ No newline at end of file diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index b888ec21e708..7b0ed0d06739 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -99,6 +99,7 @@ import com.android.server.EventLogTags; import com.android.server.FgThread; import com.android.server.SystemService; +import java.lang.reflect.InvocationTargetException; import libcore.io.IoUtils; import org.xmlpull.v1.XmlPullParser; @@ -119,14 +120,16 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; +import com.android.internal.R; -public class WallpaperManagerService extends IWallpaperManager.Stub { +public class WallpaperManagerService extends IWallpaperManager.Stub + implements IWallpaperManagerService { static final String TAG = "WallpaperManagerService"; static final boolean DEBUG = false; static final boolean DEBUG_LIVE = DEBUG || true; public static class Lifecycle extends SystemService { - private WallpaperManagerService mService; + private IWallpaperManagerService mService; public Lifecycle(Context context) { super(context); @@ -134,22 +137,30 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { @Override public void onStart() { - mService = new WallpaperManagerService(getContext()); - publishBinderService(Context.WALLPAPER_SERVICE, mService); + try { + final Class<? extends IWallpaperManagerService> klass = + (Class<? extends IWallpaperManagerService>)Class.forName( + getContext().getResources().getString( + R.string.config_wallpaperManagerServiceName)); + mService = klass.getConstructor(Context.class).newInstance(getContext()); + publishBinderService(Context.WALLPAPER_SERVICE, mService); + } catch (Exception exp) { + Slog.wtf(TAG, "Failed to instantiate WallpaperManagerService", exp); + } } @Override public void onBootPhase(int phase) { - if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) { - mService.systemReady(); - } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { - mService.switchUser(UserHandle.USER_SYSTEM, null); + if (mService != null) { + mService.onBootPhase(phase); } } @Override public void onUnlockUser(int userHandle) { - mService.onUnlockUser(userHandle); + if (mService != null) { + mService.onUnlockUser(userHandle); + } } } @@ -1255,7 +1266,17 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { mLockWallpaperMap.remove(userId); } - void onUnlockUser(final int userId) { + @Override + public void onBootPhase(int phase) { + if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) { + systemReady(); + } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { + switchUser(UserHandle.USER_SYSTEM, null); + } + } + + @Override + public void onUnlockUser(final int userId) { synchronized (mLock) { if (mCurrentUserId == userId) { if (mWaitingForUnlock) { diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java index 65951dc634f8..28b4c1dbeb8e 100644 --- a/services/core/java/com/android/server/wm/DragDropController.java +++ b/services/core/java/com/android/server/wm/DragDropController.java @@ -40,6 +40,7 @@ import android.view.View; import com.android.internal.util.Preconditions; import com.android.server.input.InputWindowHandle; import com.android.server.wm.WindowManagerInternal.IDragDropCallback; +import java.util.concurrent.atomic.AtomicReference; /** * Managing drag and drop operations initiated by View#startDragAndDrop. @@ -67,42 +68,10 @@ class DragDropController { private final Handler mHandler; /** - * Lock to preserve the order of state updates. - * The lock is used to process drag and drop state updates in order without having the window - * manager lock. - * - * Suppose DragDropController invokes a callback method A, then processes the following update - * A'. Same for a callback method B and the following update B'. The callback wants - * DragDropController to processes the updates in the order of A' then B'. - * - * Without mWriteLock: the following race can happen. - * - * 1. Thread a calls A. - * 2. Thread b calls B. - * 3. Thread b acquires the window manager lock - * 4. thread b processes the update B' - * 5. Thread a acquires the window manager lock - * 6. thread a processes the update A' - * - * With mWriteLock we can ensure the order of A' and B' - * - * 1. Thread a acquire mWriteLock - * 2. Thread a calls A - * 3. Thread a acquire the window manager lock - * 4. Thread a processes A' - * 5. Thread b acquire mWriteLock - * 6. Thread b calls B - * 7. Thread b acquire the window manager lock - * 8. Thread b processes B' - * - * Don't acquire the lock while holding the window manager lock, otherwise it causes a deadlock. - */ - private final Object mWriteLock = new Object(); - - /** * Callback which is used to sync drag state with the vendor-specific code. */ - @NonNull private IDragDropCallback mCallback = new IDragDropCallback() {}; + @NonNull private AtomicReference<IDragDropCallback> mCallback = new AtomicReference<>( + new IDragDropCallback() {}); boolean dragDropActiveLocked() { return mDragState != null; @@ -114,9 +83,7 @@ class DragDropController { void registerCallback(IDragDropCallback callback) { Preconditions.checkNotNull(callback); - synchronized (mWriteLock) { - mCallback = callback; - } + mCallback.set(callback); } DragDropController(WindowManagerService service, Looper looper) { @@ -136,45 +103,48 @@ class DragDropController { + " asbinder=" + window.asBinder()); } - synchronized (mWriteLock) { - synchronized (mService.mWindowMap) { - if (dragDropActiveLocked()) { - Slog.w(TAG_WM, "Drag already in progress"); - return null; - } + if (width <= 0 || height <= 0) { + Slog.w(TAG_WM, "width and height of drag shadow must be positive"); + return null; + } - // TODO(multi-display): support other displays - final DisplayContent displayContent = - mService.getDefaultDisplayContentLocked(); - final Display display = displayContent.getDisplay(); - - final SurfaceControl surface = new SurfaceControl.Builder(session) - .setName("drag surface") - .setSize(width, height) - .setFormat(PixelFormat.TRANSLUCENT) - .build(); - surface.setLayerStack(display.getLayerStack()); - float alpha = 1; - if ((flags & View.DRAG_FLAG_OPAQUE) == 0) { - alpha = DRAG_SHADOW_ALPHA_TRANSPARENT; - } - surface.setAlpha(alpha); - - if (SHOW_TRANSACTIONS) - Slog.i(TAG_WM, " DRAG " + surface + ": CREATE"); - outSurface.copyFrom(surface); - final IBinder winBinder = window.asBinder(); - IBinder token = new Binder(); - mDragState = new DragState(mService, token, surface, flags, winBinder); - mDragState.mPid = callerPid; - mDragState.mUid = callerUid; - mDragState.mOriginalAlpha = alpha; - token = mDragState.mToken = new Binder(); - - // 5 second timeout for this window to actually begin the drag - sendTimeoutMessage(MSG_DRAG_START_TIMEOUT, winBinder); - return token; + synchronized (mService.mWindowMap) { + if (dragDropActiveLocked()) { + Slog.w(TAG_WM, "Drag already in progress"); + return null; + } + + // TODO(multi-display): support other displays + final DisplayContent displayContent = + mService.getDefaultDisplayContentLocked(); + final Display display = displayContent.getDisplay(); + + final SurfaceControl surface = new SurfaceControl.Builder(session) + .setName("drag surface") + .setSize(width, height) + .setFormat(PixelFormat.TRANSLUCENT) + .build(); + surface.setLayerStack(display.getLayerStack()); + float alpha = 1; + if ((flags & View.DRAG_FLAG_OPAQUE) == 0) { + alpha = DRAG_SHADOW_ALPHA_TRANSPARENT; } + surface.setAlpha(alpha); + + if (SHOW_TRANSACTIONS) + Slog.i(TAG_WM, " DRAG " + surface + ": CREATE"); + outSurface.copyFrom(surface); + final IBinder winBinder = window.asBinder(); + IBinder token = new Binder(); + mDragState = new DragState(mService, token, surface, flags, winBinder); + mDragState.mPid = callerPid; + mDragState.mUid = callerUid; + mDragState.mOriginalAlpha = alpha; + token = mDragState.mToken = new Binder(); + + // 5 second timeout for this window to actually begin the drag + sendTimeoutMessage(MSG_DRAG_START_TIMEOUT, winBinder); + return token; } } @@ -185,84 +155,89 @@ class DragDropController { Slog.d(TAG_WM, "perform drag: win=" + window + " data=" + data); } - synchronized (mWriteLock) { - if (!mCallback.performDrag(window, dragToken, touchSource, touchX, touchY, thumbCenterX, - thumbCenterY, data)) { - return false; - } + final boolean callbackResult = mCallback.get().prePerformDrag(window, dragToken, + touchSource, touchX, touchY, thumbCenterX, thumbCenterY, data); + try { synchronized (mService.mWindowMap) { - if (mDragState == null) { - Slog.w(TAG_WM, "No drag prepared"); - throw new IllegalStateException("performDrag() without prepareDrag()"); - } - - if (dragToken != mDragState.mToken) { - Slog.w(TAG_WM, "Performing mismatched drag"); - throw new IllegalStateException("performDrag() does not match prepareDrag()"); - } - - final WindowState callingWin = mService.windowForClientLocked(null, window, false); - if (callingWin == null) { - Slog.w(TAG_WM, "Bad requesting window " + window); - return false; // !!! TODO: throw here? - } + mHandler.removeMessages(MSG_DRAG_START_TIMEOUT, window.asBinder()); + try { + if (!callbackResult) { + return false; + } - // !!! TODO: if input is not still focused on the initiating window, fail - // the drag initiation (e.g. an alarm window popped up just as the application - // called performDrag() + Preconditions.checkState( + mDragState != null, "performDrag() without prepareDrag()"); + Preconditions.checkState( + mDragState.mToken == dragToken, + "performDrag() does not match prepareDrag()"); + + final WindowState callingWin = mService.windowForClientLocked( + null, window, false); + if (callingWin == null) { + Slog.w(TAG_WM, "Bad requesting window " + window); + return false; // !!! TODO: throw here? + } - mHandler.removeMessages(MSG_DRAG_START_TIMEOUT, window.asBinder()); + // !!! TODO: if input is not still focused on the initiating window, fail + // the drag initiation (e.g. an alarm window popped up just as the application + // called performDrag() - // !!! TODO: extract the current touch (x, y) in screen coordinates. That - // will let us eliminate the (touchX,touchY) parameters from the API. + // !!! TODO: extract the current touch (x, y) in screen coordinates. That + // will let us eliminate the (touchX,touchY) parameters from the API. - // !!! FIXME: put all this heavy stuff onto the mHandler looper, as well as - // the actual drag event dispatch stuff in the dragstate + // !!! FIXME: put all this heavy stuff onto the mHandler looper, as well as + // the actual drag event dispatch stuff in the dragstate - final DisplayContent displayContent = callingWin.getDisplayContent(); - if (displayContent == null) { - return false; - } - Display display = displayContent.getDisplay(); - mDragState.register(display); - if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel, - mDragState.getInputChannel())) { - Slog.e(TAG_WM, "Unable to transfer touch focus"); - mDragState.closeLocked(); - return false; - } + final DisplayContent displayContent = callingWin.getDisplayContent(); + if (displayContent == null) { + Slog.w(TAG_WM, "display content is null"); + return false; + } - mDragState.mDisplayContent = displayContent; - mDragState.mData = data; - mDragState.broadcastDragStartedLocked(touchX, touchY); - mDragState.overridePointerIconLocked(touchSource); + final Display display = displayContent.getDisplay(); + mDragState.register(display); + if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel, + mDragState.getInputChannel())) { + Slog.e(TAG_WM, "Unable to transfer touch focus"); + return false; + } - // remember the thumb offsets for later - mDragState.mThumbOffsetX = thumbCenterX; - mDragState.mThumbOffsetY = thumbCenterY; + mDragState.mDisplayContent = displayContent; + mDragState.mData = data; + mDragState.broadcastDragStartedLocked(touchX, touchY); + mDragState.overridePointerIconLocked(touchSource); + // remember the thumb offsets for later + mDragState.mThumbOffsetX = thumbCenterX; + mDragState.mThumbOffsetY = thumbCenterY; + + // Make the surface visible at the proper location + final SurfaceControl surfaceControl = mDragState.mSurfaceControl; + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, ">>> OPEN TRANSACTION performDrag"); + mService.openSurfaceTransaction(); + try { + surfaceControl.setPosition(touchX - thumbCenterX, + touchY - thumbCenterY); + surfaceControl.setLayer(mDragState.getDragLayerLocked()); + surfaceControl.setLayerStack(display.getLayerStack()); + surfaceControl.show(); + } finally { + mService.closeSurfaceTransaction("performDrag"); + if (SHOW_LIGHT_TRANSACTIONS) { + Slog.i(TAG_WM, "<<< CLOSE TRANSACTION performDrag"); + } + } - // Make the surface visible at the proper location - final SurfaceControl surfaceControl = mDragState.mSurfaceControl; - if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, ">>> OPEN TRANSACTION performDrag"); - mService.openSurfaceTransaction(); - try { - surfaceControl.setPosition(touchX - thumbCenterX, - touchY - thumbCenterY); - surfaceControl.setLayer(mDragState.getDragLayerLocked()); - surfaceControl.setLayerStack(display.getLayerStack()); - surfaceControl.show(); + mDragState.notifyLocationLocked(touchX, touchY); } finally { - mService.closeSurfaceTransaction("performDrag"); - if (SHOW_LIGHT_TRANSACTIONS) { - Slog.i(TAG_WM, "<<< CLOSE TRANSACTION performDrag"); + if (mDragState != null && !mDragState.isInProgress()) { + mDragState.closeLocked(); } } - - mDragState.notifyLocationLocked(touchX, touchY); } + return true; // success! + } finally { + mCallback.get().postPerformDrag(); } - - return true; // success! } void reportDropResult(IWindow window, boolean consumed) { @@ -271,8 +246,8 @@ class DragDropController { Slog.d(TAG_WM, "Drop result=" + consumed + " reported by " + token); } - synchronized (mWriteLock) { - mCallback.reportDropResult(window, consumed); + mCallback.get().preReportDropResult(window, consumed); + try { synchronized (mService.mWindowMap) { if (mDragState == null) { // Most likely the drop recipient ANRed and we ended the drag @@ -297,10 +272,11 @@ class DragDropController { return; // !!! TODO: throw here? } - mDragState.mDragResult = consumed; mDragState.endDragLocked(); } + } finally { + mCallback.get().postReportDropResult(); } } @@ -309,8 +285,8 @@ class DragDropController { Slog.d(TAG_WM, "cancelDragAndDrop"); } - synchronized (mWriteLock) { - mCallback.cancelDragAndDrop(dragToken); + mCallback.get().preCancelDragAndDrop(dragToken); + try { synchronized (mService.mWindowMap) { if (mDragState == null) { Slog.w(TAG_WM, "cancelDragAndDrop() without prepareDrag()"); @@ -327,6 +303,8 @@ class DragDropController { mDragState.mDragResult = false; mDragState.cancelDragLocked(); } + } finally { + mCallback.get().postCancelDragAndDrop(); } } @@ -338,20 +316,18 @@ class DragDropController { * @param newY Y coordinate value in dp in the screen coordinate */ void handleMotionEvent(boolean keepHandling, float newX, float newY) { - synchronized (mWriteLock) { - synchronized (mService.mWindowMap) { - if (!dragDropActiveLocked()) { - // The drag has ended but the clean-up message has not been processed by - // window manager. Drop events that occur after this until window manager - // has a chance to clean-up the input handle. - return; - } + synchronized (mService.mWindowMap) { + if (!dragDropActiveLocked()) { + // The drag has ended but the clean-up message has not been processed by + // window manager. Drop events that occur after this until window manager + // has a chance to clean-up the input handle. + return; + } - if (keepHandling) { - mDragState.notifyMoveLocked(newX, newY); - } else { - mDragState.notifyDropLocked(newX, newY); - } + if (keepHandling) { + mDragState.notifyMoveLocked(newX, newY); + } else { + mDragState.notifyDropLocked(newX, newY); } } } @@ -414,12 +390,11 @@ class DragDropController { if (DEBUG_DRAG) { Slog.w(TAG_WM, "Timeout starting drag by win " + win); } - synchronized (mWriteLock) { - synchronized (mService.mWindowMap) { - // !!! TODO: ANR the app that has failed to start the drag in time - if (mDragState != null) { - mDragState.closeLocked(); - } + + synchronized (mService.mWindowMap) { + // !!! TODO: ANR the app that has failed to start the drag in time + if (mDragState != null) { + mDragState.closeLocked(); } } break; @@ -430,13 +405,12 @@ class DragDropController { if (DEBUG_DRAG) { Slog.w(TAG_WM, "Timeout ending drag to win " + win); } - synchronized (mWriteLock) { - synchronized (mService.mWindowMap) { - // !!! TODO: ANR the drag-receiving app - if (mDragState != null) { - mDragState.mDragResult = false; - mDragState.endDragLocked(); - } + + synchronized (mService.mWindowMap) { + // !!! TODO: ANR the drag-receiving app + if (mDragState != null) { + mDragState.mDragResult = false; + mDragState.endDragLocked(); } } break; @@ -455,15 +429,13 @@ class DragDropController { } case MSG_ANIMATION_END: { - synchronized (mWriteLock) { - synchronized (mService.mWindowMap) { - if (mDragState == null) { - Slog.wtf(TAG_WM, "mDragState unexpectedly became null while " + - "plyaing animation"); - return; - } - mDragState.closeLocked(); + synchronized (mService.mWindowMap) { + if (mDragState == null) { + Slog.wtf(TAG_WM, "mDragState unexpectedly became null while " + + "plyaing animation"); + return; } + mDragState.closeLocked(); } break; } diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index 112e62f27ea2..b9f437af20e4 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java @@ -568,6 +568,14 @@ class DragState { mToken = token; } + /** + * Returns true if it has sent DRAG_STARTED broadcast out but has not been sent DRAG_END + * broadcast. + */ + boolean isInProgress() { + return mDragInProgress; + } + private static DragEvent obtainDragEvent(WindowState win, int action, float x, float y, Object localState, ClipDescription description, ClipData data, diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 7e29a3aa811e..88b7a11f02fd 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -390,12 +390,13 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { } } - final boolean inPositioning = (mService.mTaskPositioner != null); + final boolean inPositioning = mService.mTaskPositioningController.isPositioningLocked(); if (inPositioning) { if (DEBUG_TASK_POSITIONING) { Log.d(TAG_WM, "Inserting window handle for repositioning"); } - final InputWindowHandle dragWindowHandle = mService.mTaskPositioner.mDragWindowHandle; + final InputWindowHandle dragWindowHandle = + mService.mTaskPositioningController.getDragWindowHandleLocked(); if (dragWindowHandle != null) { addInputWindowHandle(dragWindowHandle); } else { diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 63eea104c7e7..192d6c84e190 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -368,7 +368,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { long ident = Binder.clearCallingIdentity(); try { - return mService.startMovingTask(window, startX, startY); + return mService.mTaskPositioningController.startMovingTask(window, startX, startY); } finally { Binder.restoreCallingIdentity(ident); } diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java index 87d0a4016634..ca9f3a933f70 100644 --- a/services/core/java/com/android/server/wm/TaskPositioner.java +++ b/services/core/java/com/android/server/wm/TaskPositioner.java @@ -16,15 +16,11 @@ package com.android.server.wm; -import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT; -import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT; import static android.app.ActivityManager.RESIZE_MODE_USER; import static android.app.ActivityManager.RESIZE_MODE_USER_FORCED; -import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING; -import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerService.dipToPixel; @@ -44,7 +40,6 @@ import android.util.Slog; import android.view.BatchedInputEventReceiver; import android.view.Choreographer; import android.view.Display; -import android.view.DisplayInfo; import android.view.InputChannel; import android.view.InputDevice; import android.view.InputEvent; diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java new file mode 100644 index 000000000000..bb5706ceb0ec --- /dev/null +++ b/services/core/java/com/android/server/wm/TaskPositioningController.java @@ -0,0 +1,159 @@ +/* + * 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.wm; + +import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING; +import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; + +import android.annotation.Nullable; +import android.app.IActivityManager; +import android.os.RemoteException; +import android.util.Slog; +import android.view.Display; +import android.view.IWindow; +import com.android.internal.annotations.GuardedBy; +import com.android.server.input.InputManagerService; +import com.android.server.input.InputWindowHandle; + +/** + * Controller for task positioning by drag. + */ +class TaskPositioningController { + private final WindowManagerService mService; + private final InputManagerService mInputManager; + private final InputMonitor mInputMonitor; + private final IActivityManager mActivityManager; + + @GuardedBy("WindowManagerSerivce.mWindowMap") + private @Nullable TaskPositioner mTaskPositioner; + + boolean isPositioningLocked() { + return mTaskPositioner != null; + } + + InputWindowHandle getDragWindowHandleLocked() { + return mTaskPositioner != null ? mTaskPositioner.mDragWindowHandle : null; + } + + TaskPositioningController(WindowManagerService service, InputManagerService inputManager, + InputMonitor inputMonitor, IActivityManager activityManager) { + mService = service; + mInputMonitor = inputMonitor; + mInputManager = inputManager; + mActivityManager = activityManager; + } + + boolean startMovingTask(IWindow window, float startX, float startY) { + WindowState win = null; + synchronized (mService.mWindowMap) { + win = mService.windowForClientLocked(null, window, false); + // win shouldn't be null here, pass it down to startPositioningLocked + // to get warning if it's null. + if (!startPositioningLocked( + win, false /*resize*/, false /*preserveOrientation*/, startX, startY)) { + return false; + } + } + try { + mActivityManager.setFocusedTask(win.getTask().mTaskId); + } catch(RemoteException e) {} + return true; + } + + void handleTapOutsideTask(DisplayContent displayContent, int x, int y) { + int taskId = -1; + synchronized (mService.mWindowMap) { + final Task task = displayContent.findTaskForResizePoint(x, y); + if (task != null) { + if (!startPositioningLocked(task.getTopVisibleAppMainWindow(), true /*resize*/, + task.preserveOrientationOnResize(), x, y)) { + return; + } + taskId = task.mTaskId; + } else { + taskId = displayContent.taskIdFromPoint(x, y); + } + } + if (taskId >= 0) { + try { + mActivityManager.setFocusedTask(taskId); + } catch(RemoteException e) {} + } + } + + private boolean startPositioningLocked(WindowState win, boolean resize, + boolean preserveOrientation, float startX, float startY) { + if (DEBUG_TASK_POSITIONING) + Slog.d(TAG_WM, "startPositioningLocked: " + + "win=" + win + ", resize=" + resize + ", preserveOrientation=" + + preserveOrientation + ", {" + startX + ", " + startY + "}"); + + if (win == null || win.getAppToken() == null) { + Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win); + return false; + } + if (win.mInputChannel == null) { + Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, " + + " probably being removed"); + return false; + } + + final DisplayContent displayContent = win.getDisplayContent(); + if (displayContent == null) { + Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win); + return false; + } + + Display display = displayContent.getDisplay(); + mTaskPositioner = new TaskPositioner(mService); + mTaskPositioner.register(displayContent); + mInputMonitor.updateInputWindowsLw(true /*force*/); + + // We need to grab the touch focus so that the touch events during the + // resizing/scrolling are not sent to the app. 'win' is the main window + // of the app, it may not have focus since there might be other windows + // on top (eg. a dialog window). + WindowState transferFocusFromWin = win; + if (mService.mCurrentFocus != null && mService.mCurrentFocus != win + && mService.mCurrentFocus.mAppToken == win.mAppToken) { + transferFocusFromWin = mService.mCurrentFocus; + } + if (!mInputManager.transferTouchFocus( + transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) { + Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus"); + mTaskPositioner.unregister(); + mTaskPositioner = null; + mInputMonitor.updateInputWindowsLw(true /*force*/); + return false; + } + + mTaskPositioner.startDrag(win, resize, preserveOrientation, startX, startY); + return true; + } + + void finishPositioning() { + if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "finishPositioning"); + + synchronized (mService.mWindowMap) { + if (mTaskPositioner != null) { + mTaskPositioner.unregister(); + mTaskPositioner = null; + mInputMonitor.updateInputWindowsLw(true /*force*/); + } + } + } +} diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index 036f7b0aea03..62d2e7d8e1c5 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -151,23 +151,38 @@ public abstract class WindowManagerInternal { */ public interface IDragDropCallback { /** - * Called when drag operation is started. + * Called when drag operation is starting. */ - default boolean performDrag(IWindow window, IBinder dragToken, + default boolean prePerformDrag(IWindow window, IBinder dragToken, int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY, ClipData data) { return true; } /** - * Called when drop result is reported. + * Called when drag operation is started. + */ + default void postPerformDrag() {} + + /** + * Called when drop result is being reported. + */ + default void preReportDropResult(IWindow window, boolean consumed) {} + + /** + * Called when drop result was reported. + */ + default void postReportDropResult() {} + + /** + * Called when drag operation is being cancelled. */ - default void reportDropResult(IWindow window, boolean consumed) {} + default void preCancelDragAndDrop(IBinder dragToken) {} /** - * Called when drag operation is cancelled. + * Called when drag operation was cancelled. */ - default void cancelDragAndDrop(IBinder dragToken) {} + default void postCancelDragAndDrop() {} } /** diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index b43c3116ea5a..8c9948e1ee49 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -755,7 +755,7 @@ public class WindowManagerService extends IWindowManager.Stub // Whether or not a layout can cause a wake up when theater mode is enabled. boolean mAllowTheaterModeWakeFromLayout; - TaskPositioner mTaskPositioner; + final TaskPositioningController mTaskPositioningController; final DragDropController mDragDropController; // For frozen screen animations. @@ -1088,6 +1088,8 @@ public class WindowManagerService extends IWindowManager.Stub mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean( com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout); + mTaskPositioningController = + new TaskPositioningController(this, mInputManager, mInputMonitor, mActivityManager); mDragDropController = new DragDropController(this, mH.getLooper()); LocalServices.addService(WindowManagerInternal.class, new LocalService()); @@ -4442,107 +4444,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - boolean startMovingTask(IWindow window, float startX, float startY) { - WindowState win = null; - synchronized (mWindowMap) { - win = windowForClientLocked(null, window, false); - // win shouldn't be null here, pass it down to startPositioningLocked - // to get warning if it's null. - if (!startPositioningLocked( - win, false /*resize*/, false /*preserveOrientation*/, startX, startY)) { - return false; - } - } - try { - mActivityManager.setFocusedTask(win.getTask().mTaskId); - } catch(RemoteException e) {} - return true; - } - - private void handleTapOutsideTask(DisplayContent displayContent, int x, int y) { - int taskId = -1; - synchronized (mWindowMap) { - final Task task = displayContent.findTaskForResizePoint(x, y); - if (task != null) { - if (!startPositioningLocked(task.getTopVisibleAppMainWindow(), true /*resize*/, - task.preserveOrientationOnResize(), x, y)) { - return; - } - taskId = task.mTaskId; - } else { - taskId = displayContent.taskIdFromPoint(x, y); - } - } - if (taskId >= 0) { - try { - mActivityManager.setFocusedTask(taskId); - } catch(RemoteException e) {} - } - } - - private boolean startPositioningLocked(WindowState win, boolean resize, - boolean preserveOrientation, float startX, float startY) { - if (DEBUG_TASK_POSITIONING) - Slog.d(TAG_WM, "startPositioningLocked: " - + "win=" + win + ", resize=" + resize + ", preserveOrientation=" - + preserveOrientation + ", {" + startX + ", " + startY + "}"); - - if (win == null || win.getAppToken() == null) { - Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win); - return false; - } - if (win.mInputChannel == null) { - Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, " - + " probably being removed"); - return false; - } - - final DisplayContent displayContent = win.getDisplayContent(); - if (displayContent == null) { - Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win); - return false; - } - - Display display = displayContent.getDisplay(); - mTaskPositioner = new TaskPositioner(this); - mTaskPositioner.register(displayContent); - mInputMonitor.updateInputWindowsLw(true /*force*/); - - // We need to grab the touch focus so that the touch events during the - // resizing/scrolling are not sent to the app. 'win' is the main window - // of the app, it may not have focus since there might be other windows - // on top (eg. a dialog window). - WindowState transferFocusFromWin = win; - if (mCurrentFocus != null && mCurrentFocus != win - && mCurrentFocus.mAppToken == win.mAppToken) { - transferFocusFromWin = mCurrentFocus; - } - if (!mInputManager.transferTouchFocus( - transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) { - Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus"); - mTaskPositioner.unregister(); - mTaskPositioner = null; - mInputMonitor.updateInputWindowsLw(true /*force*/); - return false; - } - - mTaskPositioner.startDrag(win, resize, preserveOrientation, startX, startY); - return true; - } - - private void finishPositioning() { - if (DEBUG_TASK_POSITIONING) { - Slog.d(TAG_WM, "finishPositioning"); - } - synchronized (mWindowMap) { - if (mTaskPositioner != null) { - mTaskPositioner.unregister(); - mTaskPositioner = null; - mInputMonitor.updateInputWindowsLw(true /*force*/); - } - } - } - // ------------------------------------------------------------- // Input Events and Focus Management // ------------------------------------------------------------- @@ -5005,12 +4906,13 @@ public class WindowManagerService extends IWindowManager.Stub } case TAP_OUTSIDE_TASK: { - handleTapOutsideTask((DisplayContent)msg.obj, msg.arg1, msg.arg2); + mTaskPositioningController.handleTapOutsideTask( + (DisplayContent)msg.obj, msg.arg1, msg.arg2); } break; case FINISH_TASK_POSITIONING: { - finishPositioning(); + mTaskPositioningController.finishPositioning(); } break; diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 5d76304627c6..e53aa81c575c 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -115,7 +115,7 @@ cc_defaults { ], static_libs: [ - "android.hardware.broadcastradio@common-utils-lib", + "android.hardware.broadcastradio@common-utils-1x-lib", "libscrypt_static", ], } diff --git a/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp b/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp index e1dbdebdcb97..222ac5b903fb 100644 --- a/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp +++ b/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp @@ -25,7 +25,7 @@ #include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h> #include <android/hardware/broadcastradio/1.2/IBroadcastRadioFactory.h> #include <android/hidl/manager/1.0/IServiceManager.h> -#include <broadcastradio-utils/Utils.h> +#include <broadcastradio-utils-1x/Utils.h> #include <core_jni_helpers.h> #include <hidl/ServiceManagement.h> #include <nativehelper/JNIHelp.h> diff --git a/services/core/jni/BroadcastRadio/Tuner.cpp b/services/core/jni/BroadcastRadio/Tuner.cpp index df53feeaf8fa..63339e933cac 100644 --- a/services/core/jni/BroadcastRadio/Tuner.cpp +++ b/services/core/jni/BroadcastRadio/Tuner.cpp @@ -24,7 +24,7 @@ #include <android/hardware/broadcastradio/1.2/IBroadcastRadioFactory.h> #include <binder/IPCThreadState.h> -#include <broadcastradio-utils/Utils.h> +#include <broadcastradio-utils-1x/Utils.h> #include <core_jni_helpers.h> #include <media/AudioSystem.h> #include <nativehelper/JNIHelp.h> diff --git a/services/core/jni/BroadcastRadio/TunerCallback.cpp b/services/core/jni/BroadcastRadio/TunerCallback.cpp index d624df69a7ff..d0ba00529d0b 100644 --- a/services/core/jni/BroadcastRadio/TunerCallback.cpp +++ b/services/core/jni/BroadcastRadio/TunerCallback.cpp @@ -22,7 +22,7 @@ #include "Tuner.h" #include "convert.h" -#include <broadcastradio-utils/Utils.h> +#include <broadcastradio-utils-1x/Utils.h> #include <core_jni_helpers.h> #include <nativehelper/JNIHelp.h> #include <utils/Log.h> diff --git a/services/core/jni/BroadcastRadio/convert.cpp b/services/core/jni/BroadcastRadio/convert.cpp index 734ce793e833..f5381a8caac1 100644 --- a/services/core/jni/BroadcastRadio/convert.cpp +++ b/services/core/jni/BroadcastRadio/convert.cpp @@ -21,7 +21,7 @@ #include "regions.h" -#include <broadcastradio-utils/Utils.h> +#include <broadcastradio-utils-1x/Utils.h> #include <core_jni_helpers.h> #include <nativehelper/JNIHelp.h> #include <utils/Log.h> diff --git a/services/core/jni/BroadcastRadio/regions.cpp b/services/core/jni/BroadcastRadio/regions.cpp index b7fd0f33ccfc..1757a4d5c369 100644 --- a/services/core/jni/BroadcastRadio/regions.cpp +++ b/services/core/jni/BroadcastRadio/regions.cpp @@ -19,7 +19,7 @@ #include "regions.h" -#include <broadcastradio-utils/Utils.h> +#include <broadcastradio-utils-1x/Utils.h> #include <utils/Log.h> namespace android { diff --git a/services/core/jni/com_android_server_GraphicsStatsService.cpp b/services/core/jni/com_android_server_GraphicsStatsService.cpp index 8385020844bb..d1d253b94713 100644 --- a/services/core/jni/com_android_server_GraphicsStatsService.cpp +++ b/services/core/jni/com_android_server_GraphicsStatsService.cpp @@ -39,7 +39,7 @@ static jlong createDump(JNIEnv*, jobject, jint fd, jboolean isProto) { } static void addToDump(JNIEnv* env, jobject, jlong dumpPtr, jstring jpath, jstring jpackage, - jint versionCode, jlong startTime, jlong endTime, jbyteArray jdata) { + jlong versionCode, jlong startTime, jlong endTime, jbyteArray jdata) { std::string path; const ProfileData* data = nullptr; LOG_ALWAYS_FATAL_IF(jdata == nullptr && jpath == nullptr, "Path and data can't both be null"); @@ -78,7 +78,7 @@ static void finishDump(JNIEnv*, jobject, jlong dumpPtr) { } static void saveBuffer(JNIEnv* env, jobject clazz, jstring jpath, jstring jpackage, - jint versionCode, jlong startTime, jlong endTime, jbyteArray jdata) { + jlong versionCode, jlong startTime, jlong endTime, jbyteArray jdata) { ScopedByteArrayRO buffer(env, jdata); LOG_ALWAYS_FATAL_IF(buffer.size() != sizeof(ProfileData), "Buffer size %zu doesn't match expected %zu!", buffer.size(), sizeof(ProfileData)); @@ -96,10 +96,10 @@ static void saveBuffer(JNIEnv* env, jobject clazz, jstring jpath, jstring jpacka static const JNINativeMethod sMethods[] = { { "nGetAshmemSize", "()I", (void*) getAshmemSize }, { "nCreateDump", "(IZ)J", (void*) createDump }, - { "nAddToDump", "(JLjava/lang/String;Ljava/lang/String;IJJ[B)V", (void*) addToDump }, + { "nAddToDump", "(JLjava/lang/String;Ljava/lang/String;JJJ[B)V", (void*) addToDump }, { "nAddToDump", "(JLjava/lang/String;)V", (void*) addFileToDump }, { "nFinishDump", "(J)V", (void*) finishDump }, - { "nSaveBuffer", "(Ljava/lang/String;Ljava/lang/String;IJJ[B)V", (void*) saveBuffer }, + { "nSaveBuffer", "(Ljava/lang/String;Ljava/lang/String;JJJ[B)V", (void*) saveBuffer }, }; int register_android_server_GraphicsStatsService(JNIEnv* env) diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index b979ff46702d..7ee047b0c8d2 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.BIND_DEVICE_ADMIN; import static android.Manifest.permission.MANAGE_CA_CERTIFICATES; import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; import static android.app.ActivityManager.USER_OP_SUCCESS; +import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER; import static android.app.admin.DevicePolicyManager.CODE_ACCOUNTS_NOT_EMPTY; import static android.app.admin.DevicePolicyManager.CODE_ADD_MANAGED_PROFILE_DISALLOWED; import static android.app.admin.DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE; @@ -40,10 +41,13 @@ import static android.app.admin.DevicePolicyManager.DELEGATION_APP_RESTRICTIONS; import static android.app.admin.DevicePolicyManager.DELEGATION_BLOCK_UNINSTALL; import static android.app.admin.DevicePolicyManager.DELEGATION_CERT_INSTALL; import static android.app.admin.DevicePolicyManager.DELEGATION_ENABLE_SYSTEM_APP; +import static android.app.admin.DevicePolicyManager.DELEGATION_INSTALL_EXISTING_PACKAGE; import static android.app.admin.DevicePolicyManager.DELEGATION_KEEP_UNINSTALLED_PACKAGES; import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS; import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT; +import static android.app.admin.DevicePolicyManager.LEAVE_ALL_SYSTEM_APPS_ENABLED; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; +import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; import static android.app.admin.DevicePolicyManager.PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER; import static android.app.admin.DevicePolicyManager.START_USER_IN_BACKGROUND; import static android.app.admin.DevicePolicyManager.WIPE_EUICC; @@ -79,7 +83,6 @@ import android.app.admin.DeviceAdminInfo; import android.app.admin.DeviceAdminReceiver; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; -import android.app.admin.IDevicePolicyManager; import android.app.admin.NetworkEvent; import android.app.admin.PasswordMetrics; import android.app.admin.SecurityLog; @@ -216,6 +219,7 @@ import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; /** * Implementation of the device policy APIs. @@ -289,6 +293,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private static final String ATTR_APPLICATION_RESTRICTIONS_MANAGER = "application-restrictions-manager"; + private static final String MANAGED_PROVISIONING_PKG = "com.android.managedprovisioning"; + // Comprehensive list of delegations. private static final String DELEGATIONS[] = { DELEGATION_CERT_INSTALL, @@ -297,7 +303,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { DELEGATION_ENABLE_SYSTEM_APP, DELEGATION_KEEP_UNINSTALLED_PACKAGES, DELEGATION_PACKAGE_ACCESS, - DELEGATION_PERMISSION_GRANT + DELEGATION_PERMISSION_GRANT, + DELEGATION_INSTALL_EXISTING_PACKAGE, + DELEGATION_KEEP_UNINSTALLED_PACKAGES }; /** @@ -388,6 +396,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private final LockPatternUtils mLockPatternUtils; private final DevicePolicyConstants mConstants; private final DeviceAdminServiceController mDeviceAdminServiceController; + private final OverlayPackagesProvider mOverlayPackagesProvider; /** * Contains (package-user) pairs to remove. An entry (p, u) implies that removal of package p @@ -740,7 +749,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private static final String TAG_ORGANIZATION_NAME = "organization-name"; private static final String ATTR_LAST_NETWORK_LOGGING_NOTIFICATION = "last-notification"; private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications"; - private static final String TAG_IS_LOGOUT_BUTTON_ENABLED = "is_logout_button_enabled"; + private static final String TAG_IS_LOGOUT_ENABLED = "is_logout_enabled"; final DeviceAdminInfo info; @@ -757,7 +766,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { static final int DEF_MINIMUM_PASSWORD_NON_LETTER = 0; @NonNull PasswordMetrics minimumPasswordMetrics = new PasswordMetrics( - DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, DEF_MINIMUM_PASSWORD_LENGTH, + PASSWORD_QUALITY_UNSPECIFIED, DEF_MINIMUM_PASSWORD_LENGTH, DEF_MINIMUM_PASSWORD_LETTERS, DEF_MINIMUM_PASSWORD_UPPER_CASE, DEF_MINIMUM_PASSWORD_LOWER_CASE, DEF_MINIMUM_PASSWORD_NUMERIC, DEF_MINIMUM_PASSWORD_SYMBOLS, DEF_MINIMUM_PASSWORD_NON_LETTER); @@ -790,7 +799,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { boolean requireAutoTime = false; // Can only be set by a device owner. boolean forceEphemeralUsers = false; // Can only be set by a device owner. boolean isNetworkLoggingEnabled = false; // Can only be set by a device owner. - boolean isLogoutButtonEnabled = false; // Can only be set by a device owner. + boolean isLogoutEnabled = false; // Can only be set by a device owner. // one notification after enabling + one more after reboots static final int DEF_MAXIMUM_NETWORK_LOGGING_NOTIFICATIONS_SHOWN = 2; @@ -883,8 +892,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { out.startTag(null, TAG_POLICIES); info.writePoliciesToXml(out); out.endTag(null, TAG_POLICIES); - if (minimumPasswordMetrics.quality - != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { + if (minimumPasswordMetrics.quality != PASSWORD_QUALITY_UNSPECIFIED) { out.startTag(null, TAG_PASSWORD_QUALITY); out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordMetrics.quality)); out.endTag(null, TAG_PASSWORD_QUALITY); @@ -1108,10 +1116,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { out.text(organizationName); out.endTag(null, TAG_ORGANIZATION_NAME); } - if (isLogoutButtonEnabled) { - out.startTag(null, TAG_IS_LOGOUT_BUTTON_ENABLED); - out.attribute(null, ATTR_VALUE, Boolean.toString(isLogoutButtonEnabled)); - out.endTag(null, TAG_IS_LOGOUT_BUTTON_ENABLED); + if (isLogoutEnabled) { + out.startTag(null, TAG_IS_LOGOUT_ENABLED); + out.attribute(null, ATTR_VALUE, Boolean.toString(isLogoutEnabled)); + out.endTag(null, TAG_IS_LOGOUT_ENABLED); } } @@ -1286,8 +1294,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } else { Log.w(LOG_TAG, "Missing text when loading organization name"); } - } else if (TAG_IS_LOGOUT_BUTTON_ENABLED.equals(tag)) { - isLogoutButtonEnabled = Boolean.parseBoolean( + } else if (TAG_IS_LOGOUT_ENABLED.equals(tag)) { + isLogoutEnabled = Boolean.parseBoolean( parser.getAttributeValue(null, ATTR_VALUE)); } else { Slog.w(LOG_TAG, "Unknown admin tag: " + tag); @@ -1901,6 +1909,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mDeviceAdminServiceController = new DeviceAdminServiceController(this, mConstants); + mOverlayPackagesProvider = new OverlayPackagesProvider(mContext); + if (!mHasFeature) { // Skip the rest of the initialization return; @@ -3569,11 +3579,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public int getPasswordQuality(ComponentName who, int userHandle, boolean parent) { if (!mHasFeature) { - return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; + return PASSWORD_QUALITY_UNSPECIFIED; } enforceFullCrossUsersPermission(userHandle); synchronized (this) { - int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; + int mode = PASSWORD_QUALITY_UNSPECIFIED; if (who != null) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent); @@ -3656,30 +3666,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public int getPasswordMinimumLength(ComponentName who, int userHandle, boolean parent) { - if (!mHasFeature) { - return 0; - } - enforceFullCrossUsersPermission(userHandle); - synchronized (this) { - int length = 0; - - if (who != null) { - ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent); - return admin != null ? admin.minimumPasswordMetrics.length : length; - } - - // Return the strictest policy across all participating admins. - List<ActiveAdmin> admins = - getActiveAdminsForLockscreenPoliciesLocked(userHandle, parent); - final int N = admins.size(); - for (int i = 0; i < N; i++) { - ActiveAdmin admin = admins.get(i); - if (length < admin.minimumPasswordMetrics.length) { - length = admin.minimumPasswordMetrics.length; - } - } - return length; - } + return getStrictestPasswordRequirement(who, userHandle, parent, + admin -> admin.minimumPasswordMetrics.length, PASSWORD_QUALITY_UNSPECIFIED); } @Override @@ -3701,31 +3689,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public int getPasswordHistoryLength(ComponentName who, int userHandle, boolean parent) { - if (!mHasFeature) { - return 0; - } - enforceFullCrossUsersPermission(userHandle); - synchronized (this) { - int length = 0; - - if (who != null) { - ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent); - return admin != null ? admin.passwordHistoryLength : length; - } - - // Return the strictest policy across all participating admins. - List<ActiveAdmin> admins = - getActiveAdminsForLockscreenPoliciesLocked(userHandle, parent); - final int N = admins.size(); - for (int i = 0; i < N; i++) { - ActiveAdmin admin = admins.get(i); - if (length < admin.passwordHistoryLength) { - length = admin.passwordHistoryLength; - } - } - - return length; - } + return getStrictestPasswordRequirement(who, userHandle, parent, + admin -> admin.passwordHistoryLength, PASSWORD_QUALITY_UNSPECIFIED); } @Override @@ -3914,30 +3879,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public int getPasswordMinimumUpperCase(ComponentName who, int userHandle, boolean parent) { - if (!mHasFeature) { - return 0; - } - enforceFullCrossUsersPermission(userHandle); - synchronized (this) { - int length = 0; - - if (who != null) { - ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent); - return admin != null ? admin.minimumPasswordMetrics.upperCase : length; - } - - // Return the strictest policy across all participating admins. - List<ActiveAdmin> admins = - getActiveAdminsForLockscreenPoliciesLocked(userHandle, parent); - final int N = admins.size(); - for (int i = 0; i < N; i++) { - ActiveAdmin admin = admins.get(i); - if (length < admin.minimumPasswordMetrics.upperCase) { - length = admin.minimumPasswordMetrics.upperCase; - } - } - return length; - } + return getStrictestPasswordRequirement(who, userHandle, parent, + admin -> admin.minimumPasswordMetrics.upperCase, PASSWORD_QUALITY_COMPLEX); } @Override @@ -3956,30 +3899,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public int getPasswordMinimumLowerCase(ComponentName who, int userHandle, boolean parent) { - if (!mHasFeature) { - return 0; - } - enforceFullCrossUsersPermission(userHandle); - synchronized (this) { - int length = 0; - - if (who != null) { - ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent); - return admin != null ? admin.minimumPasswordMetrics.lowerCase : length; - } - - // Return the strictest policy across all participating admins. - List<ActiveAdmin> admins = - getActiveAdminsForLockscreenPoliciesLocked(userHandle, parent); - final int N = admins.size(); - for (int i = 0; i < N; i++) { - ActiveAdmin admin = admins.get(i); - if (length < admin.minimumPasswordMetrics.lowerCase) { - length = admin.minimumPasswordMetrics.lowerCase; - } - } - return length; - } + return getStrictestPasswordRequirement(who, userHandle, parent, + admin -> admin.minimumPasswordMetrics.lowerCase, PASSWORD_QUALITY_COMPLEX); } @Override @@ -4001,33 +3922,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public int getPasswordMinimumLetters(ComponentName who, int userHandle, boolean parent) { - if (!mHasFeature) { - return 0; - } - enforceFullCrossUsersPermission(userHandle); - synchronized (this) { - int length = 0; - - if (who != null) { - ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent); - return admin != null ? admin.minimumPasswordMetrics.letters : length; - } - - // Return the strictest policy across all participating admins. - List<ActiveAdmin> admins = - getActiveAdminsForLockscreenPoliciesLocked(userHandle, parent); - final int N = admins.size(); - for (int i = 0; i < N; i++) { - ActiveAdmin admin = admins.get(i); - if (!isLimitPasswordAllowed(admin, PASSWORD_QUALITY_COMPLEX)) { - continue; - } - if (length < admin.minimumPasswordMetrics.letters) { - length = admin.minimumPasswordMetrics.letters; - } - } - return length; - } + return getStrictestPasswordRequirement(who, userHandle, parent, + admin -> admin.minimumPasswordMetrics.letters, PASSWORD_QUALITY_COMPLEX); } @Override @@ -4049,34 +3945,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public int getPasswordMinimumNumeric(ComponentName who, int userHandle, boolean parent) { - if (!mHasFeature) { - return 0; - } - enforceFullCrossUsersPermission(userHandle); - synchronized (this) { - int length = 0; - - if (who != null) { - ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent); - return admin != null ? admin.minimumPasswordMetrics.numeric : length; - } - - // Return the strictest policy across all participating admins. - List<ActiveAdmin> admins = - getActiveAdminsForLockscreenPoliciesLocked(userHandle, parent); - final int N = admins.size(); - for (int i = 0; i < N; i++) { - ActiveAdmin admin = admins.get(i); - if (!isLimitPasswordAllowed(admin, PASSWORD_QUALITY_COMPLEX)) { - continue; - } - if (length < admin.minimumPasswordMetrics.numeric) { - length = admin.minimumPasswordMetrics.numeric; - } - } - return length; - } - } + return getStrictestPasswordRequirement(who, userHandle, parent, + admin -> admin.minimumPasswordMetrics.numeric, PASSWORD_QUALITY_COMPLEX); + } @Override public void setPasswordMinimumSymbols(ComponentName who, int length, boolean parent) { @@ -4097,33 +3968,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public int getPasswordMinimumSymbols(ComponentName who, int userHandle, boolean parent) { - if (!mHasFeature) { - return 0; - } - enforceFullCrossUsersPermission(userHandle); - synchronized (this) { - int length = 0; - - if (who != null) { - ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent); - return admin != null ? admin.minimumPasswordMetrics.symbols : length; - } - - // Return the strictest policy across all participating admins. - List<ActiveAdmin> admins = - getActiveAdminsForLockscreenPoliciesLocked(userHandle, parent); - final int N = admins.size(); - for (int i = 0; i < N; i++) { - ActiveAdmin admin = admins.get(i); - if (!isLimitPasswordAllowed(admin, PASSWORD_QUALITY_COMPLEX)) { - continue; - } - if (length < admin.minimumPasswordMetrics.symbols) { - length = admin.minimumPasswordMetrics.symbols; - } - } - return length; - } + return getStrictestPasswordRequirement(who, userHandle, parent, + admin -> admin.minimumPasswordMetrics.symbols, PASSWORD_QUALITY_COMPLEX); } @Override @@ -4145,32 +3991,40 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public int getPasswordMinimumNonLetter(ComponentName who, int userHandle, boolean parent) { + return getStrictestPasswordRequirement(who, userHandle, parent, + admin -> admin.minimumPasswordMetrics.nonLetter, PASSWORD_QUALITY_COMPLEX); + } + + /** + * Calculates strictest (maximum) value for a given password property enforced by admin[s]. + */ + private int getStrictestPasswordRequirement(ComponentName who, int userHandle, + boolean parent, Function<ActiveAdmin, Integer> getter, int minimumPasswordQuality) { if (!mHasFeature) { return 0; } enforceFullCrossUsersPermission(userHandle); synchronized (this) { - int length = 0; - if (who != null) { - ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent); - return admin != null ? admin.minimumPasswordMetrics.nonLetter : length; + final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent); + return admin != null ? getter.apply(admin) : 0; } - // Return the strictest policy across all participating admins. - List<ActiveAdmin> admins = + int maxValue = 0; + final List<ActiveAdmin> admins = getActiveAdminsForLockscreenPoliciesLocked(userHandle, parent); final int N = admins.size(); for (int i = 0; i < N; i++) { - ActiveAdmin admin = admins.get(i); - if (!isLimitPasswordAllowed(admin, PASSWORD_QUALITY_COMPLEX)) { + final ActiveAdmin admin = admins.get(i); + if (!isLimitPasswordAllowed(admin, minimumPasswordQuality)) { continue; } - if (length < admin.minimumPasswordMetrics.nonLetter) { - length = admin.minimumPasswordMetrics.nonLetter; + final Integer adminValue = getter.apply(admin); + if (adminValue > maxValue) { + maxValue = adminValue; } } - return length; + return maxValue; } } @@ -4210,7 +4064,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private boolean isActivePasswordSufficientForUserLocked( DevicePolicyData policy, int userHandle, boolean parent) { final int requiredPasswordQuality = getPasswordQuality(null, userHandle, parent); - if (requiredPasswordQuality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { + if (requiredPasswordQuality == PASSWORD_QUALITY_UNSPECIFIED) { // A special case is when there is no required password quality, then we just return // true since any password would be sufficient. This is for the scenario when a work // profile is first created so there is no information about the current password but @@ -4450,10 +4304,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { synchronized (this) { quality = getPasswordQuality(null, userHandle, /* parent */ false); if (quality == DevicePolicyManager.PASSWORD_QUALITY_MANAGED) { - quality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; + quality = PASSWORD_QUALITY_UNSPECIFIED; } final PasswordMetrics metrics = PasswordMetrics.computeForPassword(password); - if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { + if (quality != PASSWORD_QUALITY_UNSPECIFIED) { final int realQuality = metrics.quality; if (realQuality < quality && quality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) { @@ -8319,6 +8173,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final boolean ephemeral = (flags & DevicePolicyManager.MAKE_USER_EPHEMERAL) != 0; final boolean demo = (flags & DevicePolicyManager.MAKE_USER_DEMO) != 0 && UserManager.isDeviceInDemoMode(mContext); + final boolean leaveAllSystemAppsEnabled = (flags & LEAVE_ALL_SYSTEM_APPS_ENABLED) != 0; // Create user. UserHandle user = null; synchronized (this) { @@ -8333,8 +8188,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (demo) { userInfoFlags |= UserInfo.FLAG_DEMO; } + String[] disallowedPackages = null; + if (!leaveAllSystemAppsEnabled) { + disallowedPackages = mOverlayPackagesProvider.getNonRequiredApps(admin, + UserHandle.myUserId(), ACTION_PROVISION_MANAGED_USER).toArray( + new String[0]); + } UserInfo userInfo = mUserManagerInternal.createUserEvenWhenDisallowed(name, - userInfoFlags); + userInfoFlags, disallowedPackages); if (userInfo != null) { user = userInfo.getUserHandle(); } @@ -8345,11 +8206,20 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (user == null) { return null; } + + final int userHandle = user.getIdentifier(); + final Intent intent = new Intent(DevicePolicyManager.ACTION_MANAGED_USER_CREATED) + .putExtra(Intent.EXTRA_USER_HANDLE, userHandle) + .putExtra( + DevicePolicyManager.EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED, + leaveAllSystemAppsEnabled) + .setPackage(MANAGED_PROVISIONING_PKG) + .addFlags(Intent.FLAG_RECEIVER_FOREGROUND); + mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM); + final long id = mInjector.binderClearCallingIdentity(); try { final String adminPkg = admin.getPackageName(); - - final int userHandle = user.getIdentifier(); try { // Install the profile owner if not present. if (!mIPackageManager.isPackageAvailable(adminPkg, userHandle)) { @@ -8379,7 +8249,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if ((flags & START_USER_IN_BACKGROUND) != 0) { try { - mInjector.getIActivityManager().startUserInBackground(user.getIdentifier()); + mInjector.getIActivityManager().startUserInBackground(userHandle); } catch (RemoteException re) { // Does not happen, same process } @@ -8387,7 +8257,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return user; } catch (Throwable re) { - mUserManager.removeUser(user.getIdentifier()); + mUserManager.removeUser(userHandle); return null; } finally { mInjector.binderRestoreCallingIdentity(id); @@ -8539,6 +8409,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override + public boolean isEphemeralUser(ComponentName who) { + Preconditions.checkNotNull(who, "ComponentName is null"); + synchronized (this) { + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + } + + final int callingUserId = mInjector.userHandleGetCallingUserId(); + final long id = mInjector.binderClearCallingIdentity(); + try { + return mInjector.getUserManager().isUserEphemeral(callingUserId); + } finally { + mInjector.binderRestoreCallingIdentity(id); + } + } + + @Override public Bundle getApplicationRestrictions(ComponentName who, String callerPackage, String packageName) { enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, @@ -8844,6 +8730,39 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override + public boolean installExistingPackage(ComponentName who, String callerPackage, + String packageName) { + synchronized (this) { + // Ensure the caller is a PO or an install existing package delegate + enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, + DELEGATION_INSTALL_EXISTING_PACKAGE); + final int callingUserId = mInjector.userHandleGetCallingUserId(); + if (!isUserAffiliatedWithDeviceLocked(callingUserId)) { + throw new SecurityException("Admin " + who + + " is neither the device owner or affiliated user's profile owner."); + } + + final long id = mInjector.binderClearCallingIdentity(); + try { + if (VERBOSE_LOG) { + Slog.v(LOG_TAG, "installing " + packageName + " for " + + callingUserId); + } + + // Install the package. + return mIPackageManager.installExistingPackageAsUser(packageName, callingUserId, + 0 /*installFlags*/, PackageManager.INSTALL_REASON_POLICY) + == PackageManager.INSTALL_SUCCEEDED; + } catch (RemoteException re) { + // shouldn't happen + return false; + } finally { + mInjector.binderRestoreCallingIdentity(id); + } + } + } + + @Override public void setAccountManagementDisabled(ComponentName who, String accountType, boolean disabled) { if (!mHasFeature) { @@ -11555,8 +11474,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { long ident = mInjector.binderClearCallingIdentity(); try { - return ActivityManager.getService().clearApplicationUserData(packageName, callback, - userId); + return ActivityManager.getService().clearApplicationUserData(packageName, false, + callback, userId); } catch(RemoteException re) { // Same process, should not happen. } catch (SecurityException se) { @@ -11581,35 +11500,42 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override - public synchronized void setLogoutButtonEnabled(ComponentName admin, boolean enabled) { + public synchronized void setLogoutEnabled(ComponentName admin, boolean enabled) { if (!mHasFeature) { return; } Preconditions.checkNotNull(admin); getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); - if (enabled == isLogoutButtonEnabledInternalLocked()) { + if (enabled == isLogoutEnabledInternalLocked()) { // already in the requested state return; } ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); - deviceOwner.isLogoutButtonEnabled = enabled; + deviceOwner.isLogoutEnabled = enabled; saveSettingsLocked(mInjector.userHandleGetCallingUserId()); } @Override - public boolean isLogoutButtonEnabled() { + public boolean isLogoutEnabled() { if (!mHasFeature) { return false; } synchronized (this) { - return isLogoutButtonEnabledInternalLocked(); + return isLogoutEnabledInternalLocked(); } } - private boolean isLogoutButtonEnabledInternalLocked() { + private boolean isLogoutEnabledInternalLocked() { ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); - return (deviceOwner != null) && deviceOwner.isLogoutButtonEnabled; + return (deviceOwner != null) && deviceOwner.isLogoutEnabled; } + @Override + public List<String> getDisallowedSystemApps(ComponentName admin, int userId, + String provisioningAction) throws RemoteException { + enforceCanManageProfileAndDeviceOwners(); + return new ArrayList<>( + mOverlayPackagesProvider.getNonRequiredApps(admin, userId, provisioningAction)); + } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java b/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java new file mode 100644 index 000000000000..d0ec0eeebd5c --- /dev/null +++ b/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java @@ -0,0 +1,232 @@ +/* + * 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 com.android.server.devicepolicy; + +import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE; +import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE; +import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER; + +import static com.android.internal.util.Preconditions.checkNotNull; + +import android.annotation.NonNull; +import android.app.admin.DeviceAdminReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.ArraySet; +import android.view.inputmethod.InputMethodInfo; + +import com.android.internal.R; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.view.IInputMethodManager; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +/** + * Class that provides the apps that are not required on a managed device / profile according to the + * overlays provided via (vendor_|)required_apps_managed_(profile|device).xml. + */ +public class OverlayPackagesProvider { + + protected static final String TAG = "OverlayPackagesProvider"; + + private final PackageManager mPm; + private final IInputMethodManager mIInputMethodManager; + private final Context mContext; + + public OverlayPackagesProvider(Context context) { + this(context, getIInputMethodManager()); + } + + @VisibleForTesting + OverlayPackagesProvider(Context context, IInputMethodManager iInputMethodManager) { + mContext = context; + mPm = checkNotNull(context.getPackageManager()); + mIInputMethodManager = checkNotNull(iInputMethodManager); + } + + /** + * Computes non-required apps. All the system apps with a launcher that are not in + * the required set of packages will be considered as non-required apps. + * + * Note: If an app is mistakenly listed as both required and disallowed, it will be treated as + * disallowed. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param userId The userId for which the non-required apps needs to be computed. + * @param provisioningAction action indicating type of provisioning, should be one of + * {@link ACTION_PROVISION_MANAGED_DEVICE}, {@link + * ACTION_PROVISION_MANAGED_PROFILE} or + * {@link ACTION_PROVISION_MANAGED_USER}. + * @return the set of non-required apps. + */ + @NonNull + public Set<String> getNonRequiredApps(@NonNull ComponentName admin, int userId, + @NonNull String provisioningAction) { + final Set<String> nonRequiredApps = getLaunchableApps(userId); + // Newly installed system apps are uninstalled when they are not required and are either + // disallowed or have a launcher icon. + nonRequiredApps.removeAll(getRequiredApps(provisioningAction, admin.getPackageName())); + // Don't delete the system input method packages in case of Device owner provisioning. + if (ACTION_PROVISION_MANAGED_DEVICE.equals(provisioningAction) + || ACTION_PROVISION_MANAGED_USER.equals(provisioningAction)) { + nonRequiredApps.removeAll(getSystemInputMethods()); + } + nonRequiredApps.addAll(getDisallowedApps(provisioningAction)); + return nonRequiredApps; + } + + private Set<String> getLaunchableApps(int userId) { + final Intent launcherIntent = new Intent(Intent.ACTION_MAIN); + launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER); + final List<ResolveInfo> resolveInfos = mPm.queryIntentActivitiesAsUser(launcherIntent, + PackageManager.MATCH_UNINSTALLED_PACKAGES + | PackageManager.MATCH_DISABLED_COMPONENTS + | PackageManager.MATCH_DIRECT_BOOT_AWARE + | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, + userId); + final Set<String> apps = new ArraySet<>(); + for (ResolveInfo resolveInfo : resolveInfos) { + apps.add(resolveInfo.activityInfo.packageName); + } + return apps; + } + + private Set<String> getSystemInputMethods() { + // InputMethodManager is final so it cannot be mocked. + // So, we're using IInputMethodManager directly because it can be mocked. + final List<InputMethodInfo> inputMethods; + try { + inputMethods = mIInputMethodManager.getInputMethodList(); + } catch (RemoteException e) { + // Should not happen + return null; + } + final Set<String> systemInputMethods = new ArraySet<>(); + for (InputMethodInfo inputMethodInfo : inputMethods) { + ApplicationInfo applicationInfo = inputMethodInfo.getServiceInfo().applicationInfo; + if (applicationInfo.isSystemApp()) { + systemInputMethods.add(inputMethodInfo.getPackageName()); + } + } + return systemInputMethods; + } + + private Set<String> getRequiredApps(String provisioningAction, String dpcPackageName) { + final Set<String> requiredApps = new ArraySet<>(); + requiredApps.addAll(getRequiredAppsSet(provisioningAction)); + requiredApps.addAll(getVendorRequiredAppsSet(provisioningAction)); + requiredApps.add(dpcPackageName); + return requiredApps; + } + + private Set<String> getDisallowedApps(String provisioningAction) { + final Set<String> disallowedApps = new ArraySet<>(); + disallowedApps.addAll(getDisallowedAppsSet(provisioningAction)); + disallowedApps.addAll(getVendorDisallowedAppsSet(provisioningAction)); + return disallowedApps; + } + + private static IInputMethodManager getIInputMethodManager() { + final IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE); + return IInputMethodManager.Stub.asInterface(b); + } + + private Set<String> getRequiredAppsSet(String provisioningAction) { + final int resId; + switch (provisioningAction) { + case ACTION_PROVISION_MANAGED_USER: + resId = R.array.required_apps_managed_user; + break; + case ACTION_PROVISION_MANAGED_PROFILE: + resId = R.array.required_apps_managed_profile; + break; + case ACTION_PROVISION_MANAGED_DEVICE: + resId = R.array.required_apps_managed_device; + break; + default: + throw new IllegalArgumentException("Provisioning type " + + provisioningAction + " not supported."); + } + return new ArraySet<>(Arrays.asList(mContext.getResources().getStringArray(resId))); + } + + private Set<String> getDisallowedAppsSet(String provisioningAction) { + final int resId; + switch (provisioningAction) { + case ACTION_PROVISION_MANAGED_USER: + resId = R.array.disallowed_apps_managed_user; + break; + case ACTION_PROVISION_MANAGED_PROFILE: + resId = R.array.disallowed_apps_managed_profile; + break; + case ACTION_PROVISION_MANAGED_DEVICE: + resId = R.array.disallowed_apps_managed_device; + break; + default: + throw new IllegalArgumentException("Provisioning type " + + provisioningAction + " not supported."); + } + return new ArraySet<>(Arrays.asList(mContext.getResources().getStringArray(resId))); + } + + private Set<String> getVendorRequiredAppsSet(String provisioningAction) { + final int resId; + switch (provisioningAction) { + case ACTION_PROVISION_MANAGED_USER: + resId = R.array.vendor_required_apps_managed_user; + break; + case ACTION_PROVISION_MANAGED_PROFILE: + resId = R.array.vendor_required_apps_managed_profile; + break; + case ACTION_PROVISION_MANAGED_DEVICE: + resId = R.array.vendor_required_apps_managed_device; + break; + default: + throw new IllegalArgumentException("Provisioning type " + + provisioningAction + " not supported."); + } + return new ArraySet<>(Arrays.asList(mContext.getResources().getStringArray(resId))); + } + + private Set<String> getVendorDisallowedAppsSet(String provisioningAction) { + final int resId; + switch (provisioningAction) { + case ACTION_PROVISION_MANAGED_USER: + resId = R.array.vendor_disallowed_apps_managed_user; + break; + case ACTION_PROVISION_MANAGED_PROFILE: + resId = R.array.vendor_disallowed_apps_managed_profile; + break; + case ACTION_PROVISION_MANAGED_DEVICE: + resId = R.array.vendor_disallowed_apps_managed_device; + break; + default: + throw new IllegalArgumentException("Provisioning type " + + provisioningAction + " not supported."); + } + return new ArraySet<>(Arrays.asList(mContext.getResources().getStringArray(resId))); + } +} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 4c994b94e71b..7aa628af4621 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1088,14 +1088,17 @@ public final class SystemServer { } traceEnd(); - // Wifi Service must be started first for wifi-related services. - traceBeginAndSlog("StartWifi"); - mSystemServiceManager.startService(WIFI_SERVICE_CLASS); - traceEnd(); - traceBeginAndSlog("StartWifiScanning"); - mSystemServiceManager.startService( - "com.android.server.wifi.scanner.WifiScanningService"); - traceEnd(); + if (context.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_WIFI)) { + // Wifi Service must be started first for wifi-related services. + traceBeginAndSlog("StartWifi"); + mSystemServiceManager.startService(WIFI_SERVICE_CLASS); + traceEnd(); + traceBeginAndSlog("StartWifiScanning"); + mSystemServiceManager.startService( + "com.android.server.wifi.scanner.WifiScanningService"); + traceEnd(); + } if (!disableRtt) { traceBeginAndSlog("StartWifiRtt"); diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java new file mode 100644 index 000000000000..4447fe91e34e --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java @@ -0,0 +1,390 @@ +/* + * 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 com.android.server.devicepolicy; + +import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE; +import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE; +import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER; + +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.when; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.content.res.Resources; +import android.os.RemoteException; +import android.support.test.InstrumentationRegistry; +import android.test.AndroidTestCase; +import android.test.mock.MockPackageManager; +import android.view.inputmethod.InputMethodInfo; + +import com.android.internal.R; +import com.android.internal.view.IInputMethodManager; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class OverlayPackagesProviderTest extends AndroidTestCase { + private static final String TEST_DPC_PACKAGE_NAME = "dpc.package.name"; + private static final ComponentName TEST_MDM_COMPONENT_NAME = new ComponentName( + TEST_DPC_PACKAGE_NAME, "pc.package.name.DeviceAdmin"); + private static final int TEST_USER_ID = 123; + + private @Mock + Resources mResources; + private @Mock + IInputMethodManager mIInputMethodManager; + private @Mock + Context mTestContext; + private Resources mRealResources; + + private FakePackageManager mPackageManager; + private String[] mSystemAppsWithLauncher; + private OverlayPackagesProvider mHelper; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mPackageManager = new FakePackageManager(); + when(mTestContext.getResources()).thenReturn(mResources); + when(mTestContext.getPackageManager()).thenReturn(mPackageManager); + when(mTestContext.getFilesDir()).thenReturn( + InstrumentationRegistry.getTargetContext().getCacheDir()); + + setSystemInputMethods(); + setRequiredAppsManagedDevice(); + setVendorRequiredAppsManagedDevice(); + setDisallowedAppsManagedDevice(); + setVendorDisallowedAppsManagedDevice(); + setRequiredAppsManagedProfile(); + setVendorRequiredAppsManagedProfile(); + setDisallowedAppsManagedProfile(); + setVendorDisallowedAppsManagedProfile(); + setRequiredAppsManagedUser(); + setVendorRequiredAppsManagedUser(); + setDisallowedAppsManagedUser(); + setVendorDisallowedAppsManagedUser(); + + mRealResources = InstrumentationRegistry.getTargetContext().getResources(); + mHelper = new OverlayPackagesProvider(mTestContext, mIInputMethodManager); + } + + @Test + public void testAppsWithLauncherAreNonRequiredByDefault() { + setSystemAppsWithLauncher("app.a", "app.b"); + + verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_DEVICE, "app.a", "app.b"); + } + + @Test + public void testDeviceOwnerRequiredApps() { + setSystemAppsWithLauncher("app.a", "app.b", "app.c"); + setRequiredAppsManagedDevice("app.a"); + setVendorRequiredAppsManagedDevice("app.b"); + + verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_DEVICE, "app.c"); + } + + @Test + public void testProfileOwnerRequiredApps() { + setSystemAppsWithLauncher("app.a", "app.b", "app.c"); + setRequiredAppsManagedProfile("app.a"); + setVendorRequiredAppsManagedProfile("app.b"); + + verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_PROFILE, "app.c"); + } + + @Test + public void testManagedUserRequiredApps() { + setSystemAppsWithLauncher("app.a", "app.b", "app.c"); + setRequiredAppsManagedUser("app.a"); + setVendorRequiredAppsManagedUser("app.b"); + + verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_USER, "app.c"); + } + + @Test + public void testDpcIsRequired() { + setSystemAppsWithLauncher("app.a", TEST_DPC_PACKAGE_NAME); + + verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_DEVICE, "app.a"); + } + + @Test + public void testDisallowedAppsAreNonRequiredEvenIfNoLauncher() { + setSystemAppsWithLauncher(); + setDisallowedAppsManagedDevice("app.a"); + setVendorDisallowedAppsManagedDevice("app.b"); + + verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_DEVICE, "app.a", "app.b"); + } + + @Test + public void testDeviceOwnerImesAreRequired() { + setSystemAppsWithLauncher("app.a", "app.b"); + setSystemInputMethods("app.a"); + + verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_DEVICE, "app.b"); + } + + @Test + public void testProfileOwnerImesAreNonRequired() { + setSystemAppsWithLauncher("app.a", "app.b"); + setSystemInputMethods("app.a"); + + verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_PROFILE, "app.a", "app.b"); + } + + @Test + public void testManagedUserImesAreRequired() { + setSystemAppsWithLauncher("app.a", "app.b"); + setSystemInputMethods("app.a"); + + verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_USER, "app.b"); + } + + @Test + public void testDisallowedAppsAreNonInstalled() { + setSystemAppsWithLauncher("app.a"); + setDisallowedAppsManagedDevice("app.c"); + + verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_DEVICE, "app.a", "app.c"); + } + + /** + * If an app is listed as both required and disallowed, it should be only in the disallowed + * list. Therefore, it should be present in the non-required list. + */ + @Test + public void testAllowedAndDisallowedAtTheSameTimeManagedDevice() { + setDisallowedAppsManagedDevice(TEST_DPC_PACKAGE_NAME); + setRequiredAppsManagedDevice(TEST_DPC_PACKAGE_NAME); + + verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_DEVICE, TEST_DPC_PACKAGE_NAME); + } + + /** + * @see {@link #testAllowedAndDisallowedAtTheSameTimeManagedDevice} + */ + @Test + public void testAllowedAndDisallowedAtTheSameTimeManagedUser() { + setDisallowedAppsManagedUser(TEST_DPC_PACKAGE_NAME); + setRequiredAppsManagedUser(TEST_DPC_PACKAGE_NAME); + + verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_USER, TEST_DPC_PACKAGE_NAME); + } + + /** + * @see {@link #testAllowedAndDisallowedAtTheSameTimeManagedDevice} + */ + @Test + public void testAllowedAndDisallowedAtTheSameTimeManagedProfile() { + setDisallowedAppsManagedProfile(TEST_DPC_PACKAGE_NAME); + setRequiredAppsManagedProfile(TEST_DPC_PACKAGE_NAME); + + verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_PROFILE, TEST_DPC_PACKAGE_NAME); + } + + @Test + public void testNotRequiredAndDisallowedInResManagedDevice() { + verifyEmptyIntersection(R.array.required_apps_managed_device, + R.array.disallowed_apps_managed_device); + } + + @Test + public void testNotRequiredAndDisallowedInResManagedUser() { + verifyEmptyIntersection(R.array.required_apps_managed_user, + R.array.disallowed_apps_managed_user); + } + + @Test + public void testNotRequiredAndDisallowedInResManagedProfile() { + verifyEmptyIntersection(R.array.required_apps_managed_profile, + R.array.disallowed_apps_managed_profile); + } + + @Test + public void testNotRequiredAndDisallowedInResManagedDeviceVendor() { + verifyEmptyIntersection(R.array.vendor_required_apps_managed_device, + R.array.vendor_disallowed_apps_managed_device); + } + + @Test + public void testNotRequiredAndDisallowedInResManagedUserVendor() { + verifyEmptyIntersection(R.array.vendor_required_apps_managed_user, + R.array.vendor_disallowed_apps_managed_user); + } + + @Test + public void testNotRequiredAndDisallowedInResManagedProfileVendor() { + verifyEmptyIntersection(R.array.vendor_required_apps_managed_profile, + R.array.vendor_disallowed_apps_managed_profile); + } + + private ArrayList<String> getStringArrayInRealResources(int id) { + return new ArrayList<>(Arrays.asList(mRealResources.getStringArray(id))); + } + + private void verifyEmptyIntersection(int requiredId, int disallowedId) { + ArrayList<String> required = getStringArrayInRealResources(requiredId); + ArrayList<String> disallowed = getStringArrayInRealResources(disallowedId); + required.retainAll(disallowed); + assertTrue(required.isEmpty()); + } + + private void verifyAppsAreNonRequired(String action, String... appArray) { + assertEquals(listFromArray(appArray), + mHelper.getNonRequiredApps(TEST_MDM_COMPONENT_NAME, TEST_USER_ID, action)); + } + + private void setRequiredAppsManagedDevice(String... apps) { + setStringArray(R.array.required_apps_managed_device, apps); + } + + private void setVendorRequiredAppsManagedDevice(String... apps) { + setStringArray(R.array.vendor_required_apps_managed_device, apps); + } + + private void setDisallowedAppsManagedDevice(String... apps) { + setStringArray(R.array.disallowed_apps_managed_device, apps); + } + + private void setVendorDisallowedAppsManagedDevice(String... apps) { + setStringArray(R.array.vendor_disallowed_apps_managed_device, apps); + } + + private void setRequiredAppsManagedProfile(String... apps) { + setStringArray(R.array.required_apps_managed_profile, apps); + } + + private void setVendorRequiredAppsManagedProfile(String... apps) { + setStringArray(R.array.vendor_required_apps_managed_profile, apps); + } + + private void setDisallowedAppsManagedProfile(String... apps) { + setStringArray(R.array.disallowed_apps_managed_profile, apps); + } + + private void setVendorDisallowedAppsManagedProfile(String... apps) { + setStringArray(R.array.vendor_disallowed_apps_managed_profile, apps); + } + + private void setRequiredAppsManagedUser(String... apps) { + setStringArray(R.array.required_apps_managed_user, apps); + } + + private void setVendorRequiredAppsManagedUser(String... apps) { + setStringArray(R.array.vendor_required_apps_managed_user, apps); + } + + private void setDisallowedAppsManagedUser(String... apps) { + setStringArray(R.array.disallowed_apps_managed_user, apps); + } + + private void setVendorDisallowedAppsManagedUser(String... apps) { + setStringArray(R.array.vendor_disallowed_apps_managed_user, apps); + } + + private void setStringArray(int resourceId, String[] strs) { + when(mResources.getStringArray(eq(resourceId))) + .thenReturn(strs); + } + + private void setSystemInputMethods(String... packageNames) { + List<InputMethodInfo> inputMethods = new ArrayList<InputMethodInfo>(); + for (String packageName : packageNames) { + ApplicationInfo aInfo = new ApplicationInfo(); + aInfo.flags = ApplicationInfo.FLAG_SYSTEM; + ServiceInfo serviceInfo = new ServiceInfo(); + serviceInfo.applicationInfo = aInfo; + serviceInfo.packageName = packageName; + serviceInfo.name = ""; + ResolveInfo ri = new ResolveInfo(); + ri.serviceInfo = serviceInfo; + InputMethodInfo inputMethodInfo = new InputMethodInfo(ri, false, null, null, 0, false); + inputMethods.add(inputMethodInfo); + } + try { + when(mIInputMethodManager.getInputMethodList()).thenReturn(inputMethods); + } catch (RemoteException e) { + fail(e.toString()); + } + } + + private void setSystemAppsWithLauncher(String... apps) { + mSystemAppsWithLauncher = apps; + } + + private <T> Set<T> setFromArray(T... array) { + if (array == null) { + return null; + } + return new HashSet<T>(Arrays.asList(array)); + } + + private <T> List<T> listFromArray(T... array) { + if (array == null) { + return null; + } + return Arrays.asList(array); + } + + class FakePackageManager extends MockPackageManager { + @Override + public List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId) { + assertTrue("Expected an intent with action ACTION_MAIN", + Intent.ACTION_MAIN.equals(intent.getAction())); + assertEquals("Expected an intent with category CATEGORY_LAUNCHER", + setFromArray(Intent.CATEGORY_LAUNCHER), intent.getCategories()); + assertTrue("Expected the flag MATCH_UNINSTALLED_PACKAGES", + (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0); + assertTrue("Expected the flag MATCH_DISABLED_COMPONENTS", + (flags & PackageManager.MATCH_DISABLED_COMPONENTS) != 0); + assertTrue("Expected the flag MATCH_DIRECT_BOOT_AWARE", + (flags & PackageManager.MATCH_DIRECT_BOOT_AWARE) != 0); + assertTrue("Expected the flag MATCH_DIRECT_BOOT_UNAWARE", + (flags & PackageManager.MATCH_DIRECT_BOOT_UNAWARE) != 0); + assertEquals(userId, TEST_USER_ID); + List<ResolveInfo> result = new ArrayList<>(); + if (mSystemAppsWithLauncher == null) { + return result; + } + for (String packageName : mSystemAppsWithLauncher) { + ActivityInfo ai = new ActivityInfo(); + ai.packageName = packageName; + ResolveInfo ri = new ResolveInfo(); + ri.activityInfo = ai; + result.add(ri); + } + return result; + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java new file mode 100644 index 000000000000..2629b12375a4 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java @@ -0,0 +1,230 @@ +/* + * 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 com.android.server.display; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import android.os.PowerManager; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; +import android.util.Spline; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Arrays; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class BrightnessMappingStrategyTest { + + private static final float[] LUX_LEVELS = { + 0f, + 5f, + 20f, + 40f, + 100f, + 325f, + 600f, + 1250f, + 2200f, + 4000f, + 5000f + }; + + private static final float[] DISPLAY_LEVELS_NITS = { + 13.25f, + 54.0f, + 78.85f, + 105.02f, + 132.7f, + 170.12f, + 212.1f, + 265.2f, + 335.8f, + 415.2f, + 478.5f, + }; + + private static final int[] DISPLAY_LEVELS_BACKLIGHT = { + 9, + 30, + 45, + 62, + 78, + 96, + 119, + 146, + 178, + 221, + 255 + }; + + private static final float[] DISPLAY_RANGE_NITS = { 2.685f, 478.5f }; + private static final int[] BACKLIGHT_RANGE = { 1, 255 }; + + @Test + public void testSimpleStrategyMappingAtControlPoints() { + BrightnessMappingStrategy simple = BrightnessMappingStrategy.create( + LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT, + null /*brightnessLevelsNits*/, null /*nitsRange*/, null /*backlightRange*/); + assertNotNull("BrightnessMappingStrategy should not be null", simple); + for (int i = 0; i < LUX_LEVELS.length; i++) { + final float expectedLevel = + (float) DISPLAY_LEVELS_BACKLIGHT[i] / PowerManager.BRIGHTNESS_ON; + assertEquals(expectedLevel, + simple.getBrightness(LUX_LEVELS[i]), 0.01f /*tolerance*/); + } + } + + @Test + public void testSimpleStrategyMappingBetweenControlPoints() { + BrightnessMappingStrategy simple = BrightnessMappingStrategy.create( + LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT, + null /*brightnessLevelsNits*/, null /*nitsRange*/, null /*backlightRange*/); + assertNotNull("BrightnessMappingStrategy should not be null", simple); + for (int i = 1; i < LUX_LEVELS.length; i++) { + final float lux = (LUX_LEVELS[i - 1] + LUX_LEVELS[i]) / 2; + final float backlight = simple.getBrightness(lux) * PowerManager.BRIGHTNESS_ON; + assertTrue("Desired brightness should be between adjacent control points.", + backlight > DISPLAY_LEVELS_BACKLIGHT[i-1] + && backlight < DISPLAY_LEVELS_BACKLIGHT[i]); + } + } + + @Test + public void testPhysicalStrategyMappingAtControlPoints() { + BrightnessMappingStrategy physical = BrightnessMappingStrategy.create( + LUX_LEVELS, null /*brightnessLevelsBacklight*/, + DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); + assertNotNull("BrightnessMappingStrategy should not be null", physical); + for (int i = 0; i < LUX_LEVELS.length; i++) { + final float expectedLevel = DISPLAY_LEVELS_NITS[i] / DISPLAY_RANGE_NITS[1]; + assertEquals(expectedLevel, + physical.getBrightness(LUX_LEVELS[i]), 0.01f /*tolerance*/); + } + } + + @Test + public void testPhysicalStrategyMappingBetweenControlPoints() { + BrightnessMappingStrategy physical = BrightnessMappingStrategy.create( + LUX_LEVELS, null /*brightnessLevelsBacklight*/, + DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); + assertNotNull("BrightnessMappingStrategy should not be null", physical); + Spline backlightToBrightness = + Spline.createSpline(toFloatArray(BACKLIGHT_RANGE), DISPLAY_RANGE_NITS); + for (int i = 1; i < LUX_LEVELS.length; i++) { + final float lux = (LUX_LEVELS[i - 1] + LUX_LEVELS[i]) / 2; + final float backlight = physical.getBrightness(lux) * PowerManager.BRIGHTNESS_ON; + final float nits = backlightToBrightness.interpolate(backlight); + assertTrue("Desired brightness should be between adjacent control points.", + nits > DISPLAY_LEVELS_NITS[i-1] && nits < DISPLAY_LEVELS_NITS[i]); + } + } + + @Test + public void testDefaultStrategyIsPhysical() { + BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create( + LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT, + DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); + assertTrue(strategy instanceof BrightnessMappingStrategy.PhysicalMappingStrategy); + } + + @Test + public void testNonStrictlyIncreasingLuxLevelsFails() { + final float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length); + final int idx = lux.length / 2; + float tmp = lux[idx]; + lux[idx] = lux[idx+1]; + lux[idx+1] = tmp; + BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create( + lux, null /*brightnessLevelsBacklight*/, + DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); + assertNull(strategy); + + // And make sure we get the same result even if it's monotone but not increasing. + lux[idx] = lux[idx+1]; + strategy = BrightnessMappingStrategy.create( + lux, null /*brightnessLevelsBacklight*/, + DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); + assertNull(strategy); + } + + @Test + public void testDifferentNumberOfControlPointValuesFails() { + //Extra lux level + final float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length+1); + // Make sure it's strictly increasing so that the only failure is the differing array + // lengths + lux[lux.length - 1] = lux[lux.length - 2] + 1; + BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create( + lux, null /*brightnessLevelsBacklight*/, + DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); + assertNull(strategy); + + strategy = BrightnessMappingStrategy.create( + lux, DISPLAY_LEVELS_BACKLIGHT, + null /*brightnessLevelsNits*/, null /*nitsRange*/, null /*backlightRange*/); + assertNull(strategy); + + // Extra backlight level + final int[] backlight = Arrays.copyOf( + DISPLAY_LEVELS_BACKLIGHT, DISPLAY_LEVELS_BACKLIGHT.length+1); + backlight[backlight.length - 1] = backlight[backlight.length - 2] + 1; + strategy = BrightnessMappingStrategy.create( + LUX_LEVELS, backlight, + null /*brightnessLevelsNits*/, null /*nitsRange*/, null /*backlightRange*/); + assertNull(strategy); + + // Extra nits level + final float[] nits = Arrays.copyOf(DISPLAY_RANGE_NITS, DISPLAY_LEVELS_NITS.length+1); + nits[nits.length - 1] = nits[nits.length - 2] + 1; + strategy = BrightnessMappingStrategy.create( + LUX_LEVELS, null /*brightnessLevelsBacklight*/, + nits, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE); + assertNull(strategy); + } + + @Test + public void testPhysicalStrategyRequiresNitsMapping() { + BrightnessMappingStrategy physical = BrightnessMappingStrategy.create( + LUX_LEVELS, null /*brightnessLevelsBacklight*/, + DISPLAY_LEVELS_NITS, null, BACKLIGHT_RANGE); + assertNull(physical); + + physical = BrightnessMappingStrategy.create( + LUX_LEVELS, null /*brightnessLevelsBacklight*/, + DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, null); + assertNull(physical); + + physical = BrightnessMappingStrategy.create( + LUX_LEVELS, null /*brightnessLevelsBacklight*/, + DISPLAY_LEVELS_NITS, null, null); + assertNull(physical); + } + + private static float[] toFloatArray(int[] vals) { + float[] newVals = new float[vals.length]; + for (int i = 0; i < vals.length; i++) { + newVals[i] = (float) vals[i]; + } + return newVals; + } +} diff --git a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java new file mode 100644 index 000000000000..0cc37b48184e --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java @@ -0,0 +1,223 @@ +/* + * 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 com.android.server.display; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import android.hardware.display.BrightnessConfiguration; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; +import android.util.AtomicFile; +import android.util.Pair; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.FileInputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class PersistentDataStoreTest { + private PersistentDataStore mDataStore; + private TestInjector mInjector; + + @Before + public void setUp() { + mInjector = new TestInjector(); + mDataStore = new PersistentDataStore(mInjector); + } + + @Test + public void testLoadingBrightnessConfigurations() { + String contents = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + + "<display-manager-state>\n" + + " <brightness-configurations>\n" + + " <brightness-configuration user-serial=\"1\">\n" + + " <brightness-curve>\n" + + " <brightness-point lux=\"0\" nits=\"13.25\"/>\n" + + " <brightness-point lux=\"25\" nits=\"35.94\"/>\n" + + " </brightness-curve>\n" + + " </brightness-configuration>\n" + + " <brightness-configuration user-serial=\"3\">\n" + + " <brightness-curve>\n" + + " <brightness-point lux=\"0\" nits=\"13.25\"/>\n" + + " <brightness-point lux=\"10.2\" nits=\"15\"/>\n" + + " </brightness-curve>\n" + + " </brightness-configuration>\n" + + " </brightness-configurations>\n" + + "</display-manager-state>\n"; + InputStream is = new ByteArrayInputStream(contents.getBytes(StandardCharsets.UTF_8)); + mInjector.setReadStream(is); + mDataStore.loadIfNeeded(); + BrightnessConfiguration config = mDataStore.getBrightnessConfiguration(1 /*userSerial*/); + Pair<float[], float[]> curve = config.getCurve(); + float[] expectedLux = { 0f, 25f }; + float[] expectedNits = { 13.25f, 35.94f }; + assertArrayEquals(expectedLux, curve.first, "lux"); + assertArrayEquals(expectedNits, curve.second, "nits"); + + config = mDataStore.getBrightnessConfiguration(3 /*userSerial*/); + curve = config.getCurve(); + expectedLux = new float[] { 0f, 10.2f }; + expectedNits = new float[] { 13.25f, 15f }; + assertArrayEquals(expectedLux, curve.first, "lux"); + assertArrayEquals(expectedNits, curve.second, "nits"); + } + + @Test + public void testBrightnessConfigWithInvalidCurveIsIgnored() { + String contents = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + + "<display-manager-state>\n" + + " <brightness-configurations>\n" + + " <brightness-configuration user-serial=\"0\">\n" + + " <brightness-curve>\n" + + " <brightness-point lux=\"1\" nits=\"13.25\"/>\n" + + " <brightness-point lux=\"25\" nits=\"35.94\"/>\n" + + " </brightness-curve>\n" + + " </brightness-configuration>\n" + + " </brightness-configurations>\n" + + "</display-manager-state>\n"; + InputStream is = new ByteArrayInputStream(contents.getBytes(StandardCharsets.UTF_8)); + mInjector.setReadStream(is); + mDataStore.loadIfNeeded(); + assertNull(mDataStore.getBrightnessConfiguration(0 /*userSerial*/)); + } + + @Test + public void testBrightnessConfigWithInvalidFloatsIsIgnored() { + String contents = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + + "<display-manager-state>\n" + + " <brightness-configurations>\n" + + " <brightness-configuration user-serial=\"0\">\n" + + " <brightness-curve>\n" + + " <brightness-point lux=\"0\" nits=\"13.25\"/>\n" + + " <brightness-point lux=\"0xFF\" nits=\"foo\"/>\n" + + " </brightness-curve>\n" + + " </brightness-configuration>\n" + + " </brightness-configurations>\n" + + "</display-manager-state>\n"; + InputStream is = new ByteArrayInputStream(contents.getBytes(StandardCharsets.UTF_8)); + mInjector.setReadStream(is); + mDataStore.loadIfNeeded(); + assertNull(mDataStore.getBrightnessConfiguration(0 /*userSerial*/)); + } + + @Test + public void testEmptyBrightnessConfigurationsDoesntCrash() { + String contents = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + + "<display-manager-state>\n" + + " <brightness-configurations />\n" + + "</display-manager-state>\n"; + InputStream is = new ByteArrayInputStream(contents.getBytes(StandardCharsets.UTF_8)); + mInjector.setReadStream(is); + mDataStore.loadIfNeeded(); + assertNull(mDataStore.getBrightnessConfiguration(0 /*userSerial*/)); + } + + @Test + public void testStoreAndReloadOfBrightnessConfigurations() { + final float[] lux = { 0f, 10f }; + final float[] nits = {1f, 100f }; + final BrightnessConfiguration config = new BrightnessConfiguration.Builder() + .setCurve(lux, nits) + .build(); + mDataStore.loadIfNeeded(); + assertNull(mDataStore.getBrightnessConfiguration(0 /*userSerial*/)); + mDataStore.setBrightnessConfigurationForUser(config, 0); + + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + mInjector.setWriteStream(baos); + mDataStore.saveIfNeeded(); + assertTrue(mInjector.wasWriteSuccessful()); + + TestInjector newInjector = new TestInjector(); + PersistentDataStore newDataStore = new PersistentDataStore(newInjector); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + newInjector.setReadStream(bais); + newDataStore.loadIfNeeded(); + assertNotNull(newDataStore.getBrightnessConfiguration(0 /*userSerial*/)); + assertEquals(mDataStore.getBrightnessConfiguration(0 /*userSerial*/), + newDataStore.getBrightnessConfiguration(0 /*userSerial*/)); + } + + public class TestInjector extends PersistentDataStore.Injector { + private InputStream mReadStream; + private OutputStream mWriteStream; + + private boolean mWasSuccessful; + + @Override + public InputStream openRead() throws FileNotFoundException { + if (mReadStream != null) { + return mReadStream; + } else { + throw new FileNotFoundException(); + } + } + + @Override + public OutputStream startWrite() { + return mWriteStream; + } + + @Override + public void finishWrite(OutputStream os, boolean success) { + mWasSuccessful = success; + try { + os.close(); + } catch (IOException e) { + // This method can't throw IOException since the super implementation doesn't, so + // we just wrap it in a RuntimeException so we end up crashing the test all the + // same. + throw new RuntimeException(e); + } + } + + public void setReadStream(InputStream is) { + mReadStream = is; + } + + public void setWriteStream(OutputStream os) { + mWriteStream = os; + } + + public boolean wasWriteSuccessful() { + return mWasSuccessful; + } + } + + private static void assertArrayEquals(float[] expected, float[] actual, String name) { + assertEquals("Expected " + name + " arrays to be the same length!", + expected.length, actual.length); + for (int i = 0; i < expected.length; i++) { + assertEquals("Expected " + name + " arrays to be equivalent when value " + i + + "differs", expected[i], actual[i], 0.01 /*tolerance*/); + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java new file mode 100644 index 000000000000..298a98822caa --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java @@ -0,0 +1,155 @@ +/* + * 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.locksettings.recoverablekeystore; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.security.keystore.AndroidKeyStoreSecretKey; +import android.security.keystore.KeyGenParameterSpec; +import android.security.keystore.KeyProperties; +import android.security.keystore.KeyProtection; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.security.KeyStore; + +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class RecoverableKeyGeneratorTest { + private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore"; + private static final String KEY_ALGORITHM = "AES"; + private static final String TEST_ALIAS = "karlin"; + private static final String WRAPPING_KEY_ALIAS = "RecoverableKeyGeneratorTestWrappingKey"; + + @Mock + RecoverableKeyStorage mRecoverableKeyStorage; + + @Captor ArgumentCaptor<KeyProtection> mKeyProtectionArgumentCaptor; + + private AndroidKeyStoreSecretKey mPlatformKey; + private SecretKey mKeyHandle; + private RecoverableKeyGenerator mRecoverableKeyGenerator; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mPlatformKey = generateAndroidKeyStoreKey(); + mKeyHandle = generateKey(); + mRecoverableKeyGenerator = RecoverableKeyGenerator.newInstance( + mPlatformKey, mRecoverableKeyStorage); + + when(mRecoverableKeyStorage.loadFromAndroidKeyStore(any())).thenReturn(mKeyHandle); + } + + @After + public void tearDown() throws Exception { + KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER); + keyStore.load(/*param=*/ null); + keyStore.deleteEntry(WRAPPING_KEY_ALIAS); + } + + @Test + public void generateAndStoreKey_setsKeyInKeyStore() throws Exception { + mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS); + + verify(mRecoverableKeyStorage, times(1)) + .importIntoAndroidKeyStore(eq(TEST_ALIAS), any(), any()); + } + + @Test + public void generateAndStoreKey_storesKeyEnabledForEncryptDecrypt() throws Exception { + mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS); + + KeyProtection keyProtection = getKeyProtectionUsed(); + assertEquals(KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT, + keyProtection.getPurposes()); + } + + @Test + public void generateAndStoreKey_storesKeyEnabledForGCM() throws Exception { + mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS); + + KeyProtection keyProtection = getKeyProtectionUsed(); + assertArrayEquals(new String[] { KeyProperties.BLOCK_MODE_GCM }, + keyProtection.getBlockModes()); + } + + @Test + public void generateAndStoreKey_storesKeyEnabledForNoPadding() throws Exception { + mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS); + + KeyProtection keyProtection = getKeyProtectionUsed(); + assertArrayEquals(new String[] { KeyProperties.ENCRYPTION_PADDING_NONE }, + keyProtection.getEncryptionPaddings()); + } + + @Test + public void generateAndStoreKey_storesWrappedKey() throws Exception { + mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS); + + verify(mRecoverableKeyStorage, times(1)).persistToDisk(eq(TEST_ALIAS), any()); + } + + @Test + public void generateAndStoreKey_returnsKeyHandle() throws Exception { + SecretKey secretKey = mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS); + + assertEquals(mKeyHandle, secretKey); + } + + private KeyProtection getKeyProtectionUsed() throws Exception { + verify(mRecoverableKeyStorage, times(1)).importIntoAndroidKeyStore( + any(), any(), mKeyProtectionArgumentCaptor.capture()); + return mKeyProtectionArgumentCaptor.getValue(); + } + + private SecretKey generateKey() throws Exception { + KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); + keyGenerator.init(/*keySize=*/ 256); + return keyGenerator.generateKey(); + } + + private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception { + KeyGenerator keyGenerator = KeyGenerator.getInstance( + KEY_ALGORITHM, + ANDROID_KEY_STORE_PROVIDER); + keyGenerator.init(new KeyGenParameterSpec.Builder( + WRAPPING_KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) + .setBlockModes(KeyProperties.BLOCK_MODE_GCM) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) + .build()); + return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java new file mode 100644 index 000000000000..4cd5631c9b8d --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java @@ -0,0 +1,90 @@ +/* + * 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.locksettings.recoverablekeystore; + +import static org.junit.Assert.assertEquals; + +import android.security.keystore.AndroidKeyStoreSecretKey; +import android.security.keystore.KeyGenParameterSpec; +import android.security.keystore.KeyProperties; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.security.KeyStore; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.spec.GCMParameterSpec; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class WrappedKeyTest { + private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore"; + private static final String KEY_ALGORITHM = "AES"; + private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding"; + private static final String WRAPPING_KEY_ALIAS = "WrappedKeyTestWrappingKeyAlias"; + private static final int GCM_TAG_LENGTH_BYTES = 16; + private static final int BITS_PER_BYTE = 8; + private static final int GCM_TAG_LENGTH_BITS = GCM_TAG_LENGTH_BYTES * BITS_PER_BYTE; + + @After + public void tearDown() throws Exception { + KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER); + keyStore.load(/*param=*/ null); + keyStore.deleteEntry(WRAPPING_KEY_ALIAS); + } + + @Test + public void fromSecretKey_createsWrappedKeyThatCanBeUnwrapped() throws Exception { + SecretKey wrappingKey = generateAndroidKeyStoreKey(); + SecretKey rawKey = generateKey(); + + WrappedKey wrappedKey = WrappedKey.fromSecretKey(wrappingKey, rawKey); + + Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); + cipher.init( + Cipher.UNWRAP_MODE, + wrappingKey, + new GCMParameterSpec(GCM_TAG_LENGTH_BITS, wrappedKey.getNonce())); + SecretKey unwrappedKey = (SecretKey) cipher.unwrap( + wrappedKey.getKeyMaterial(), KEY_ALGORITHM, Cipher.SECRET_KEY); + assertEquals(rawKey, unwrappedKey); + } + + private SecretKey generateKey() throws Exception { + KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM); + keyGenerator.init(/*keySize=*/ 256); + return keyGenerator.generateKey(); + } + + private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception { + KeyGenerator keyGenerator = KeyGenerator.getInstance( + KEY_ALGORITHM, + ANDROID_KEY_STORE_PROVIDER); + keyGenerator.init(new KeyGenParameterSpec.Builder( + WRAPPING_KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) + .setBlockModes(KeyProperties.BLOCK_MODE_GCM) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) + .build()); + return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java b/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java index 3fd1d556df14..b2eb57267cec 100644 --- a/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java @@ -16,19 +16,28 @@ package com.android.server.pm; +import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageStats; import android.os.SystemClock; import android.os.UserHandle; -import android.test.AndroidTestCase; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; import android.util.Log; import com.android.internal.util.ArrayUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; + import java.util.Arrays; -public class InstallerTest extends AndroidTestCase { +@RunWith(AndroidJUnit4.class) +public class InstallerTest { private static final String TAG = "InstallerTest"; private Installer mInstaller; @@ -64,7 +73,7 @@ public class InstallerTest extends AndroidTestCase { } } - @Override + @Before public void setUp() throws Exception { mInstaller = new Installer(getContext()); mInstaller.onStart(); @@ -72,13 +81,15 @@ public class InstallerTest extends AndroidTestCase { mQuota.reset(); } - @Override + @After public void tearDown() throws Exception { Log.i(TAG, mManual.toString()); Log.i(TAG, mQuota.toString()); mInstaller = null; } + @Test + @Ignore("b/68819006") public void testGetAppSize() throws Exception { int[] appIds = null; @@ -119,6 +130,8 @@ public class InstallerTest extends AndroidTestCase { } } + @Test + @Ignore("b/68819006") public void testGetUserSize() throws Exception { final int[] appIds = getAppIds(UserHandle.USER_SYSTEM); @@ -138,6 +151,8 @@ public class InstallerTest extends AndroidTestCase { checkEquals(Arrays.toString(appIds), stats, quotaStats); } + @Test + @Ignore("b/68819006") public void testGetExternalSize() throws Exception { final int[] appIds = getAppIds(UserHandle.USER_SYSTEM); @@ -167,6 +182,10 @@ public class InstallerTest extends AndroidTestCase { return appIds; } + private static Context getContext() { + return InstrumentationRegistry.getContext(); + } + private static void checkEquals(String msg, PackageStats a, PackageStats b) { checkEquals(msg + " codeSize", a.codeSize, b.codeSize); checkEquals(msg + " dataSize", a.dataSize, b.dataSize); diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java index 0995f2e35d50..fafae6c71355 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java @@ -206,8 +206,8 @@ public class PackageManagerSettingsTests { new File(InstrumentationRegistry.getContext().getFilesDir(), "com.android.bar-1"); private static final File UPDATED_CODE_PATH = new File(InstrumentationRegistry.getContext().getFilesDir(), "com.android.bar-2"); - private static final int INITIAL_VERSION_CODE = 10023; - private static final int UPDATED_VERSION_CODE = 10025; + private static final long INITIAL_VERSION_CODE = 10023L; + private static final long UPDATED_VERSION_CODE = 10025L; @Test public void testPackageStateCopy01() { diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java index 36cc3a059eac..32b0b266bafc 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java @@ -520,6 +520,10 @@ public class PackageParserTest { pkg.featureGroups = new ArrayList<>(); pkg.featureGroups.add(new FeatureGroupInfo()); + + pkg.mCompileSdkVersionCodename = "foo23"; + pkg.mCompileSdkVersion = 100; + pkg.mVersionCodeMajor = 100; } private static void assertAllFieldsExist(PackageParser.Package pkg) throws Exception { diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java index ee33e797b0ab..2257960f6450 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java @@ -121,6 +121,8 @@ import java.util.function.BiConsumer; @SmallTest public class ShortcutManagerTest1 extends BaseShortcutManagerTest { + private static final boolean SKIP_FOR_BUG_67325252 = true; + /** * Test for the first launch path, no settings file available. */ @@ -722,6 +724,10 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { } public void testCleanupDanglingBitmaps() throws Exception { + if (SKIP_FOR_BUG_67325252) { + return; + } + assertBitmapDirectories(USER_0, EMPTY_STRINGS); assertBitmapDirectories(USER_10, EMPTY_STRINGS); diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java index b57cac06ce6e..74013b792f07 100644 --- a/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java +++ b/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java @@ -25,6 +25,7 @@ import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import java.io.File; +import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; @@ -33,6 +34,7 @@ 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.fail; @SmallTest public class PackageStatusStorageTest { @@ -48,6 +50,7 @@ public class PackageStatusStorageTest { // Using the instrumentation context means the database is created in a test app-specific // directory. mPackageStatusStorage = new PackageStatusStorage(dataDir); + mPackageStatusStorage.initialize(); } @After @@ -56,6 +59,16 @@ public class PackageStatusStorageTest { } @Test + public void initialize_fail() { + File readOnlyDir = new File("/system/does/not/exist"); + PackageStatusStorage packageStatusStorage = new PackageStatusStorage(readOnlyDir); + try { + packageStatusStorage.initialize(); + fail(); + } catch (IOException expected) {} + } + + @Test public void getPackageStatus_initialState() { assertNull(mPackageStatusStorage.getPackageStatus()); } diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java index 0ea8d4f5e353..9cf6392cab97 100644 --- a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java +++ b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java @@ -30,8 +30,13 @@ import android.provider.TimeZoneRulesDataContract; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; +import java.io.File; +import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import java.time.Clock; +import java.time.Instant; +import java.time.ZoneId; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -57,7 +62,7 @@ public class PackageTrackerTest { private ConfigHelper mMockConfigHelper; private PackageManagerHelper mMockPackageManagerHelper; - private FakeClockHelper mFakeClock; + private FakeClock mFakeClock; private FakeIntentHelper mFakeIntentHelper; private PackageStatusStorage mPackageStatusStorage; private PackageTracker mPackageTracker; @@ -66,7 +71,7 @@ public class PackageTrackerTest { public void setUp() throws Exception { Context context = InstrumentationRegistry.getContext(); - mFakeClock = new FakeClockHelper(); + mFakeClock = new FakeClock(); // Read-only interfaces so are easy to mock. mMockConfigHelper = mock(ConfigHelper.class); @@ -101,7 +106,7 @@ public class PackageTrackerTest { configureTrackingDisabled(); // Initialize the tracker. - mPackageTracker.start(); + assertFalse(mPackageTracker.start()); // Check the IntentHelper was not initialized. mFakeIntentHelper.assertNotInitialized(); @@ -116,7 +121,7 @@ public class PackageTrackerTest { configureTrackingDisabled(); // Initialize the tracker. - mPackageTracker.start(); + assertFalse(mPackageTracker.start()); // Check reliability triggering state. mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); @@ -138,7 +143,7 @@ public class PackageTrackerTest { configureTrackingDisabled(); // Initialize the tracker. - mPackageTracker.start(); + assertFalse(mPackageTracker.start()); // Check reliability triggering state. mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); @@ -163,7 +168,7 @@ public class PackageTrackerTest { mPackageStatusStorage.generateCheckToken(INITIAL_APP_PACKAGE_VERSIONS); // Initialize the tracker. - mPackageTracker.start(); + assertFalse(mPackageTracker.start()); // Check reliability triggering state. mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); @@ -259,6 +264,35 @@ public class PackageTrackerTest { } @Test + public void trackingEnabled_storageInitializationFails() throws Exception { + // Create a PackageStateStorage that will fail to initialize. + PackageStatusStorage packageStatusStorage = + new PackageStatusStorage(new File("/system/does/not/exist")); + + // Create a new PackageTracker to use the bad storage. + mPackageTracker = new PackageTracker( + mFakeClock, + mMockConfigHelper, + mMockPackageManagerHelper, + packageStatusStorage, + mFakeIntentHelper); + + // Set up device configuration. + configureTrackingEnabled(); + configureReliabilityConfigSettingsOk(); + configureValidApplications(); + + // Initialize the tracker. + assertFalse(mPackageTracker.start()); + + // Check the IntentHelper was not initialized. + mFakeIntentHelper.assertNotInitialized(); + + // Check reliability triggering state. + mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); + } + + @Test public void trackingEnabled_packageUpdate_badUpdateAppManifestEntry() throws Exception { // Set up device configuration. configureTrackingEnabled(); @@ -266,7 +300,7 @@ public class PackageTrackerTest { configureValidApplications(); // Initialize the tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -303,7 +337,7 @@ public class PackageTrackerTest { configureValidApplications(); // Initialize the tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -348,7 +382,7 @@ public class PackageTrackerTest { configureValidApplications(); // Initialize the tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -396,7 +430,7 @@ public class PackageTrackerTest { configureValidApplications(); // Initialize the tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -435,7 +469,7 @@ public class PackageTrackerTest { configureValidApplications(); // Initialize the tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -481,7 +515,7 @@ public class PackageTrackerTest { configureValidApplications(); // Initialize the tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -530,7 +564,7 @@ public class PackageTrackerTest { configureValidApplications(); // Initialize the tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -590,7 +624,7 @@ public class PackageTrackerTest { configureValidApplications(); // Initialize the package tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -652,7 +686,7 @@ public class PackageTrackerTest { configureValidApplications(); // Initialize the package tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -708,7 +742,7 @@ public class PackageTrackerTest { configureValidApplications(); // Initialize the package tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -757,7 +791,7 @@ public class PackageTrackerTest { PackageVersions packageVersions = configureValidApplications(); // Initialize the package tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -794,7 +828,7 @@ public class PackageTrackerTest { PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions); // Initialize the package tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -834,7 +868,7 @@ public class PackageTrackerTest { PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions); // Initialize the package tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -880,7 +914,7 @@ public class PackageTrackerTest { PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions); // Initialize the package tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -939,7 +973,7 @@ public class PackageTrackerTest { PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions); // Initialize the package tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -1014,7 +1048,7 @@ public class PackageTrackerTest { PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions); // Initialize the package tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -1080,7 +1114,7 @@ public class PackageTrackerTest { PackageStatus.CHECK_COMPLETED_SUCCESS, currentPackageVersions); // Initialize the package tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -1135,7 +1169,7 @@ public class PackageTrackerTest { PackageStatus.CHECK_COMPLETED_SUCCESS, currentPackageVersions); // Initialize the package tracker. - mPackageTracker.start(); + assertTrue(mPackageTracker.start()); // Check the intent helper is properly configured. checkIntentHelperInitializedAndReliabilityTrackingEnabled(); @@ -1444,18 +1478,33 @@ public class PackageTrackerTest { } } - private static class FakeClockHelper implements ClockHelper { + private static class FakeClock extends Clock { private long currentTime = 1000; @Override - public long currentTimestamp() { + public long millis() { return currentTime; } public void incrementClock(long millis) { currentTime += millis; } + + @Override + public ZoneId getZone() { + throw new UnsupportedOperationException(); + } + + @Override + public Clock withZone(ZoneId zone) { + throw new UnsupportedOperationException(); + } + + @Override + public Instant instant() { + throw new UnsupportedOperationException(); + } } /** diff --git a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java index 401f585886a2..1938487c6d2f 100644 --- a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java @@ -202,10 +202,10 @@ public class WebViewUpdateServiceTest { private static PackageInfo createPackageInfo(String packageName, boolean enabled, boolean valid, boolean installed, Signature[] signatures, long updateTime, boolean hidden, - int versionCode, boolean isSystemApp) { + long versionCode, boolean isSystemApp) { PackageInfo p = createPackageInfo(packageName, enabled, valid, installed, signatures, updateTime, hidden); - p.versionCode = versionCode; + p.setLongVersionCode(versionCode); p.applicationInfo.versionCode = versionCode; if (isSystemApp) p.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; return p; @@ -1495,7 +1495,7 @@ public class WebViewUpdateServiceTest { public void testGetCurrentWebViewPackage() { PackageInfo firstPackage = createPackageInfo("first", true /* enabled */, true /* valid */, true /* installed */); - firstPackage.versionCode = 100; + firstPackage.setLongVersionCode(100); firstPackage.versionName = "first package version"; WebViewProviderInfo[] packages = new WebViewProviderInfo[] { new WebViewProviderInfo(firstPackage.packageName, "", true, false, null)}; diff --git a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java new file mode 100644 index 000000000000..ce76a223ef20 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java @@ -0,0 +1,88 @@ +/* + * 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.wm; + +import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; +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.Matchers.anyInt; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.os.IBinder; +import android.platform.test.annotations.Presubmit; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; +import android.view.InputChannel; +import android.view.Surface; +import android.view.SurfaceSession; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +/** + * Tests for the {@link DragDropController} class. + * + * atest com.android.server.wm.DragDropControllerTests + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +@Presubmit +public class DragDropControllerTests extends WindowTestsBase { + private static final int TIMEOUT_MS = 1000; + private DragDropController mTarget; + private WindowState mWindow; + private IBinder mToken; + + @Before + public void setUp() throws Exception { + super.setUp(); + assertNotNull(sWm.mDragDropController); + mTarget = sWm.mDragDropController; + mWindow = createWindow(null, TYPE_BASE_APPLICATION, "window"); + synchronized (sWm.mWindowMap) { + // Because sWm is a static object, the previous operation may remain. + assertFalse(mTarget.dragDropActiveLocked()); + } + } + + @After + public void tearDown() { + if (mToken != null) { + mTarget.cancelDragAndDrop(mToken); + } + } + + @Test + public void testPrepareDrag() throws Exception { + final Surface surface = new Surface(); + mToken = mTarget.prepareDrag( + new SurfaceSession(), 0, 0, mWindow.mClient, 0, 100, 100, surface); + assertNotNull(mToken); + } + + @Test + public void testPrepareDrag_ZeroSizeSurface() throws Exception { + final Surface surface = new Surface(); + mToken = mTarget.prepareDrag( + new SurfaceSession(), 0, 0, mWindow.mClient, 0, 0, 0, surface); + assertNull(mToken); + } +} diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java new file mode 100644 index 000000000000..89447a912c21 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java @@ -0,0 +1,115 @@ +/* + * 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.wm; + +import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; +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.Matchers.anyInt; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.platform.test.annotations.Presubmit; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; +import android.view.InputChannel; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +/** + * Tests for the {@link TaskPositioningController} class. + * + * atest com.android.server.wm.TaskPositioningControllerTests + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +@Presubmit +public class TaskPositioningControllerTests extends WindowTestsBase { + private static final int TIMEOUT_MS = 1000; + private TaskPositioningController mTarget; + private WindowState mWindow; + + @Before + public void setUp() throws Exception { + super.setUp(); + + assertNotNull(sWm.mTaskPositioningController); + mTarget = sWm.mTaskPositioningController; + + when(sWm.mInputManager.transferTouchFocus( + any(InputChannel.class), + any(InputChannel.class))).thenReturn(true); + + mWindow = createWindow(null, TYPE_BASE_APPLICATION, "window"); + mWindow.mInputChannel = new InputChannel(); + synchronized (sWm.mWindowMap) { + sWm.mWindowMap.put(mWindow.mClient.asBinder(), mWindow); + } + } + + @Test + public void testStartAndFinishPositioning() throws Exception { + synchronized (sWm.mWindowMap) { + assertFalse(mTarget.isPositioningLocked()); + assertNull(mTarget.getDragWindowHandleLocked()); + } + + assertTrue(mTarget.startMovingTask(mWindow.mClient, 0, 0)); + + synchronized (sWm.mWindowMap) { + assertTrue(mTarget.isPositioningLocked()); + assertNotNull(mTarget.getDragWindowHandleLocked()); + } + + assertTrue(sWm.mH.runWithScissors(() -> { + mTarget.finishPositioning(); + }, TIMEOUT_MS)); + + assertFalse(mTarget.isPositioningLocked()); + assertNull(mTarget.getDragWindowHandleLocked()); + } + + @Test + public void testHandleTapOutsideTask() throws Exception { + synchronized (sWm.mWindowMap) { + + assertFalse(mTarget.isPositioningLocked()); + assertNull(mTarget.getDragWindowHandleLocked()); + } + + final DisplayContent content = mock(DisplayContent.class); + when(content.findTaskForResizePoint(anyInt(), anyInt())).thenReturn(mWindow.getTask()); + assertNotNull(mWindow.getTask().getTopVisibleAppMainWindow()); + + mTarget.handleTapOutsideTask(content, 0, 0); + + synchronized (sWm.mWindowMap) { + assertTrue(mTarget.isPositioningLocked()); + assertNotNull(mTarget.getDragWindowHandleLocked()); + } + + assertTrue(sWm.mH.runWithScissors(() -> { + mTarget.finishPositioning(); + }, TIMEOUT_MS)); + + assertFalse(mTarget.isPositioningLocked()); + assertNull(mTarget.getDragWindowHandleLocked()); + } +} diff --git a/services/tests/shortcutmanagerutils/Android.mk b/services/tests/shortcutmanagerutils/Android.mk index 0848fd51fa71..019bcbd37628 100644 --- a/services/tests/shortcutmanagerutils/Android.mk +++ b/services/tests/shortcutmanagerutils/Android.mk @@ -21,7 +21,6 @@ LOCAL_SRC_FILES := \ LOCAL_JAVA_LIBRARIES := \ mockito-target \ - legacy-android-test \ android.test.runner.stubs LOCAL_MODULE_TAGS := optional 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 55ec133a29da..0343ab2d14f4 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -92,7 +92,9 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.*; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.mockito.stubbing.Answer; import java.io.BufferedInputStream; @@ -873,6 +875,77 @@ public class NotificationManagerServiceTest extends NotificationTestCase { } @Test + public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag() + throws Exception { + final NotificationRecord parent = generateNotificationRecord( + mTestNotificationChannel, 1, "group", true); + final NotificationRecord child = generateNotificationRecord( + mTestNotificationChannel, 2, "group", false); + final NotificationRecord child2 = generateNotificationRecord( + mTestNotificationChannel, 3, "group", false); + child2.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE; + final NotificationRecord newGroup = generateNotificationRecord( + mTestNotificationChannel, 4, "group2", false); + mService.addNotification(parent); + mService.addNotification(child); + mService.addNotification(child2); + mService.addNotification(newGroup); + mService.getBinderService().cancelNotificationsFromListener(null, null); + waitForIdle(); + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(parent.sbn.getPackageName()); + assertEquals(0, notifs.length); + } + + @Test + public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter() + throws Exception { + final NotificationRecord parent = generateNotificationRecord( + mTestNotificationChannel, 1, "group", true); + final NotificationRecord child = generateNotificationRecord( + mTestNotificationChannel, 2, "group", false); + final NotificationRecord child2 = generateNotificationRecord( + mTestNotificationChannel, 3, "group", false); + child2.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE; + final NotificationRecord newGroup = generateNotificationRecord( + mTestNotificationChannel, 4, "group2", false); + mService.addNotification(parent); + mService.addNotification(child); + mService.addNotification(child2); + mService.addNotification(newGroup); + String[] keys = {parent.sbn.getKey(), child.sbn.getKey(), + child2.sbn.getKey(), newGroup.sbn.getKey()}; + mService.getBinderService().cancelNotificationsFromListener(null, keys); + waitForIdle(); + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(parent.sbn.getPackageName()); + assertEquals(1, notifs.length); + } + + @Test + public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception { + final NotificationRecord parent = generateNotificationRecord( + mTestNotificationChannel, 1, "group", true); + final NotificationRecord child = generateNotificationRecord( + mTestNotificationChannel, 2, "group", false); + final NotificationRecord child2 = generateNotificationRecord( + mTestNotificationChannel, 3, "group", false); + child2.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE; + final NotificationRecord newGroup = generateNotificationRecord( + mTestNotificationChannel, 4, "group2", false); + mService.addNotification(parent); + mService.addNotification(child); + mService.addNotification(child2); + mService.addNotification(newGroup); + mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), + parent.getUserId()); + waitForIdle(); + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(parent.sbn.getPackageName()); + assertEquals(0, notifs.length); + } + + @Test public void testFindGroupNotificationsLocked() throws Exception { // make sure the same notification can be found in both lists and returned final NotificationRecord group1 = generateNotificationRecord( @@ -912,6 +985,157 @@ public class NotificationManagerServiceTest extends NotificationTestCase { } @Test + public void testCancelAllNotifications_CancelsNoClearFlagOnGoing() throws Exception { + final NotificationRecord notif = generateNotificationRecord( + mTestNotificationChannel, 1, "group", true); + notif.getNotification().flags |= Notification.FLAG_NO_CLEAR; + mService.addNotification(notif); + mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, + Notification.FLAG_ONGOING_EVENT, true, notif.getUserId(), 0, null); + waitForIdle(); + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(notif.sbn.getPackageName()); + assertEquals(0, notifs.length); + } + + @Test + public void testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter() + throws Exception { + final NotificationRecord parent = generateNotificationRecord( + mTestNotificationChannel, 1, "group", true); + final NotificationRecord child = generateNotificationRecord( + mTestNotificationChannel, 2, "group", false); + final NotificationRecord child2 = generateNotificationRecord( + mTestNotificationChannel, 3, "group", false); + child2.getNotification().flags |= Notification.FLAG_NO_CLEAR; + final NotificationRecord newGroup = generateNotificationRecord( + mTestNotificationChannel, 4, "group2", false); + mService.addNotification(parent); + mService.addNotification(child); + mService.addNotification(child2); + mService.addNotification(newGroup); + String[] keys = {parent.sbn.getKey(), child.sbn.getKey(), + child2.sbn.getKey(), newGroup.sbn.getKey()}; + mService.getBinderService().cancelNotificationsFromListener(null, keys); + waitForIdle(); + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(parent.sbn.getPackageName()); + assertEquals(0, notifs.length); + } + + @Test + public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception { + final StatusBarNotification sbn = generateNotificationRecord(null).sbn; + sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; + mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", + sbn.getId(), sbn.getNotification(), sbn.getUserId()); + mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); + waitForIdle(); + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(sbn.getPackageName()); + assertEquals(0, notifs.length); + } + + @Test + public void testCancelAllNotifications_CancelsOnGoingFlag() throws Exception { + final NotificationRecord notif = generateNotificationRecord( + mTestNotificationChannel, 1, "group", true); + notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; + mService.addNotification(notif); + mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true, + notif.getUserId(), 0, null); + waitForIdle(); + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(notif.sbn.getPackageName()); + assertEquals(0, notifs.length); + } + + @Test + public void testUserInitiatedCancelAllOnClearAll_OnGoingFlag() throws Exception { + final NotificationRecord notif = generateNotificationRecord( + mTestNotificationChannel, 1, "group", true); + notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; + mService.addNotification(notif); + + mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), + notif.getUserId()); + waitForIdle(); + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(notif.sbn.getPackageName()); + assertEquals(1, notifs.length); + } + + @Test + public void testCancelAllCancelNotificationsFromListener_OnGoingFlag() throws Exception { + final NotificationRecord parent = generateNotificationRecord( + mTestNotificationChannel, 1, "group", true); + final NotificationRecord child = generateNotificationRecord( + mTestNotificationChannel, 2, "group", false); + final NotificationRecord child2 = generateNotificationRecord( + mTestNotificationChannel, 3, "group", false); + child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; + final NotificationRecord newGroup = generateNotificationRecord( + mTestNotificationChannel, 4, "group2", false); + mService.addNotification(parent); + mService.addNotification(child); + mService.addNotification(child2); + mService.addNotification(newGroup); + mService.getBinderService().cancelNotificationsFromListener(null, null); + waitForIdle(); + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(parent.sbn.getPackageName()); + assertEquals(1, notifs.length); + } + + @Test + public void testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter() + throws Exception { + final NotificationRecord parent = generateNotificationRecord( + mTestNotificationChannel, 1, "group", true); + final NotificationRecord child = generateNotificationRecord( + mTestNotificationChannel, 2, "group", false); + final NotificationRecord child2 = generateNotificationRecord( + mTestNotificationChannel, 3, "group", false); + child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; + final NotificationRecord newGroup = generateNotificationRecord( + mTestNotificationChannel, 4, "group2", false); + mService.addNotification(parent); + mService.addNotification(child); + mService.addNotification(child2); + mService.addNotification(newGroup); + String[] keys = {parent.sbn.getKey(), child.sbn.getKey(), + child2.sbn.getKey(), newGroup.sbn.getKey()}; + mService.getBinderService().cancelNotificationsFromListener(null, keys); + waitForIdle(); + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(parent.sbn.getPackageName()); + assertEquals(0, notifs.length); + } + + @Test + public void testUserInitiatedCancelAllWithGroup_OnGoingFlag() throws Exception { + final NotificationRecord parent = generateNotificationRecord( + mTestNotificationChannel, 1, "group", true); + final NotificationRecord child = generateNotificationRecord( + mTestNotificationChannel, 2, "group", false); + final NotificationRecord child2 = generateNotificationRecord( + mTestNotificationChannel, 3, "group", false); + child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; + final NotificationRecord newGroup = generateNotificationRecord( + mTestNotificationChannel, 4, "group2", false); + mService.addNotification(parent); + mService.addNotification(child); + mService.addNotification(child2); + mService.addNotification(newGroup); + mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), + parent.getUserId()); + waitForIdle(); + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(parent.sbn.getPackageName()); + assertEquals(1, notifs.length); + } + + @Test public void testTvExtenderChannelOverride_onTv() throws Exception { mService.setIsTelevision(true); mService.setRankingHelper(mRankingHelper); diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java index 6ac4b36a6ad7..620922ac1363 100644 --- a/services/usage/java/com/android/server/usage/AppIdleHistory.java +++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java @@ -42,6 +42,8 @@ import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; /** * Keeps track of recent active state changes in apps. @@ -334,6 +336,16 @@ public class AppIdleHistory { return appUsageHistory.currentBucket; } + public Map<String, Integer> getAppStandbyBuckets(int userId, long elapsedRealtime) { + ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId); + int size = userHistory.size(); + HashMap<String, Integer> buckets = new HashMap<>(size); + for (int i = 0; i < size; i++) { + buckets.put(userHistory.keyAt(i), userHistory.valueAt(i).currentBucket); + } + return buckets; + } + public String getAppStandbyReason(String packageName, int userId, long elapsedRealtime) { ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId); AppUsageHistory appUsageHistory = diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java index d8086bb4a92d..46efbd059d52 100644 --- a/services/usage/java/com/android/server/usage/AppStandbyController.java +++ b/services/usage/java/com/android/server/usage/AppStandbyController.java @@ -84,6 +84,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; /** * Manages the standby state of an app, listening to various events. @@ -774,13 +775,23 @@ public class AppStandbyController { return STANDBY_BUCKET_ACTIVE; } - return mAppIdleHistory.getAppStandbyBucket(packageName, userId, elapsedRealtime); + synchronized (mAppIdleLock) { + return mAppIdleHistory.getAppStandbyBucket(packageName, userId, elapsedRealtime); + } + } + + public Map<String, Integer> getAppStandbyBuckets(int userId, long elapsedRealtime) { + synchronized (mAppIdleLock) { + return mAppIdleHistory.getAppStandbyBuckets(userId, elapsedRealtime); + } } void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket, String reason, long elapsedRealtime) { - mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime, newBucket, - reason); + synchronized (mAppIdleLock) { + mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime, newBucket, + reason); + } maybeInformListeners(packageName, userId, elapsedRealtime, newBucket); } diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java index 21b11b058160..82f800128beb 100644 --- a/services/usage/java/com/android/server/usage/StorageStatsService.java +++ b/services/usage/java/com/android/server/usage/StorageStatsService.java @@ -164,6 +164,14 @@ public class StorageStatsService extends IStorageStatsManager.Stub { } @Override + public boolean isReservedSupported(String volumeUuid, String callingPackage) { + enforcePermission(Binder.getCallingUid(), callingPackage); + + // TODO: implement as part of b/62024591 + return false; + } + + @Override public long getTotalBytes(String volumeUuid, String callingPackage) { // NOTE: No permissions required diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 0572771ab6e0..15284d5e3dec 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -68,7 +68,10 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Map; /** * A service that collects, aggregates, and persists application usage data. @@ -741,6 +744,68 @@ public class UsageStatsService extends SystemService implements } @Override + public Map getAppStandbyBuckets(String callingPackageName, int userId) { + final int callingUid = Binder.getCallingUid(); + try { + userId = ActivityManager.getService().handleIncomingUser( + Binder.getCallingPid(), callingUid, userId, false, false, + "getAppStandbyBucket", null); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + if (!hasPermission(callingPackageName)) { + throw new SecurityException( + "Don't have permission to query app standby bucket"); + } + final long token = Binder.clearCallingIdentity(); + try { + return mAppStandby.getAppStandbyBuckets(userId, + SystemClock.elapsedRealtime()); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override + public void setAppStandbyBuckets(Map appBuckets, int userId) { + getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE, + "No permission to change app standby state"); + + final int callingUid = Binder.getCallingUid(); + try { + userId = ActivityManager.getService().handleIncomingUser( + Binder.getCallingPid(), callingUid, userId, false, true, + "setAppStandbyBucket", null); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + final long token = Binder.clearCallingIdentity(); + try { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + Map<String, Integer> buckets = (Map<String, Integer>) appBuckets; + for (Map.Entry<String, Integer> entry: buckets.entrySet()) { + String packageName = entry.getKey(); + int bucket = entry.getValue(); + if (bucket < UsageStatsManager.STANDBY_BUCKET_ACTIVE + || bucket > UsageStatsManager.STANDBY_BUCKET_NEVER) { + throw new IllegalArgumentException( + "Cannot set the standby bucket to " + bucket); + } + // Caller cannot set their own standby state + if (mPackageManagerInternal.getPackageUid(packageName, + PackageManager.MATCH_ANY_USER, userId) == callingUid) { + throw new IllegalArgumentException("Cannot set your own standby bucket"); + } + mAppStandby.setAppStandbyBucket(packageName, userId, bucket, + UsageStatsManager.REASON_PREDICTED + ":" + callingUid, + elapsedRealtime); + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override public void whitelistAppTemporarily(String packageName, long duration, int userId) throws RemoteException { StringBuilder reason = new StringBuilder(32); diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java index 74b9465070c5..fcfc5931ac7b 100644 --- a/telecomm/java/android/telecom/PhoneAccount.java +++ b/telecomm/java/android/telecom/PhoneAccount.java @@ -964,6 +964,9 @@ public final class PhoneAccount implements Parcelable { if (hasCapabilities(CAPABILITY_SIM_SUBSCRIPTION)) { sb.append("SimSub "); } + if (hasCapabilities(CAPABILITY_RTT)) { + sb.append("Rtt"); + } return sb.toString(); } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index e9feb8993471..ead8849c363e 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -735,12 +735,11 @@ public class CarrierConfigManager { public static final String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool"; /** - * Flag specifying whether signal strength is hidden in SIM Status screen, - * default to false. - * @hide + * Flag specifying whether the {@link android.telephony.SignalStrength} is shown in the SIM + * Status screen. The default value is true. */ - public static final String KEY_HIDE_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL = - "hide_signal_strength_in_sim_status_bool"; + public static final String KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL = + "show_signal_strength_in_sim_status_bool"; /** * Flag specifying whether an additional (client initiated) intent needs to be sent on System @@ -1310,6 +1309,19 @@ public class CarrierConfigManager { */ public static final String KEY_ALLOW_HOLD_IN_IMS_CALL_BOOL = "allow_hold_in_ims_call"; + + /** + * Flag indicating whether the carrier always wants to play an "on-hold" tone when a call has + * been remotely held. + * <p> + * When {@code true}, if the IMS stack indicates that the call session has been held, a signal + * will be sent from Telephony to play an audible "on-hold" tone played to the user. + * When {@code false}, a hold tone will only be played if the audio session becomes inactive. + * @hide + */ + public static final String KEY_ALWAYS_PLAY_REMOTE_HOLD_TONE_BOOL = + "always_play_remote_hold_tone_bool"; + /** * When true, indicates that adding a call is disabled when there is an ongoing video call * or when there is an ongoing call on wifi which was downgraded from video and VoWifi is @@ -1648,6 +1660,11 @@ public class CarrierConfigManager { "show_ims_registration_status_bool"; /** + * Flag indicating whether the carrier supports RTT over IMS. + */ + public static final String KEY_RTT_SUPPORTED_BOOL = "rtt_supported_bool"; + + /** * The flag to disable the popup dialog which warns the user of data charges. * @hide */ @@ -1706,6 +1723,7 @@ public class CarrierConfigManager { static { sDefaults = new PersistableBundle(); sDefaults.putBoolean(KEY_ALLOW_HOLD_IN_IMS_CALL_BOOL, true); + sDefaults.putBoolean(KEY_ALWAYS_PLAY_REMOTE_HOLD_TONE_BOOL, false); sDefaults.putBoolean(KEY_ADDITIONAL_CALL_SETTING_BOOL, true); sDefaults.putBoolean(KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL, false); sDefaults.putBoolean(KEY_ALLOW_LOCAL_DTMF_TONES_BOOL, true); @@ -1782,7 +1800,7 @@ public class CarrierConfigManager { sDefaults.putString(KEY_CARRIER_VVM_PACKAGE_NAME_STRING, ""); sDefaults.putStringArray(KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY, null); sDefaults.putBoolean(KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL, false); - sDefaults.putBoolean(KEY_HIDE_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL, false); + sDefaults.putBoolean(KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL, true); sDefaults.putBoolean(KEY_CI_ACTION_ON_SYS_UPDATE_BOOL, false); sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING, ""); sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING, ""); @@ -1978,6 +1996,7 @@ public class CarrierConfigManager { sDefaults.putStringArray(KEY_NON_ROAMING_OPERATOR_STRING_ARRAY, null); sDefaults.putStringArray(KEY_ROAMING_OPERATOR_STRING_ARRAY, null); sDefaults.putBoolean(KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, false); + sDefaults.putBoolean(KEY_RTT_SUPPORTED_BOOL, false); sDefaults.putBoolean(KEY_DISABLE_CHARGE_INDICATION_BOOL, false); sDefaults.putStringArray(KEY_FEATURE_ACCESS_CODES_STRING_ARRAY, null); sDefaults.putBoolean(KEY_IDENTIFY_HIGH_DEFINITION_CALLS_IN_CALL_LOG_BOOL, false); diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index fdedf758975a..7ab75f545bd3 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -390,112 +390,6 @@ public final class SmsManager { } /** - * Send a text based SMS with messaging options. - * - * @param destinationAddress the address to send the message to - * @param scAddress is the service center address or null to use - * the current default SMSC - * @param text the body of the message to send - * @param sentIntent if not NULL this <code>PendingIntent</code> is - * broadcast when the message is successfully sent, or failed. - * The result code will be <code>Activity.RESULT_OK</code> for success, - * or one of these errors:<br> - * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> - * <code>RESULT_ERROR_RADIO_OFF</code><br> - * <code>RESULT_ERROR_NULL_PDU</code><br> - * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include - * the extra "errorCode" containing a radio technology specific value, - * generally only useful for troubleshooting.<br> - * The per-application based SMS control checks sentIntent. If sentIntent - * is NULL the caller will be checked against all unknown applications, - * which cause smaller number of SMS to be sent in checking period. - * @param deliveryIntent if not NULL this <code>PendingIntent</code> is - * broadcast when the message is delivered to the recipient. The - * raw pdu of the status report is in the extended data ("pdu"). - * @param priority Priority level of the message - * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 - * --------------------------------- - * PRIORITY | Level of Priority - * --------------------------------- - * '00' | Normal - * '01' | Interactive - * '10' | Urgent - * '11' | Emergency - * ---------------------------------- - * Any Other values included Negative considered as Invalid Priority Indicator of the message. - * @param expectMore is a boolean to indicate the sending messages through same link or not. - * @param validityPeriod Validity Period of the message in mins. - * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. - * Validity Period(Minimum) -> 5 mins - * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). - * Any Other values included Negative considered as Invalid Validity Period of the message. - * - * @throws IllegalArgumentException if destinationAddress or text are empty - * {@hide} - */ - public void sendTextMessage( - String destinationAddress, String scAddress, String text, - PendingIntent sentIntent, PendingIntent deliveryIntent, - int priority, boolean expectMore, int validityPeriod) { - sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent, - true /* persistMessage*/, priority, expectMore, validityPeriod); - } - - private void sendTextMessageInternal( - String destinationAddress, String scAddress, String text, - PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage, - int priority, boolean expectMore, int validityPeriod) { - if (TextUtils.isEmpty(destinationAddress)) { - throw new IllegalArgumentException("Invalid destinationAddress"); - } - - if (TextUtils.isEmpty(text)) { - throw new IllegalArgumentException("Invalid message body"); - } - - if (priority < 0x00 || priority > 0x03) { - throw new IllegalArgumentException("Invalid priority"); - } - - if (validityPeriod < 0x05 || validityPeriod > 0x09b0a0) { - throw new IllegalArgumentException("Invalid validity period"); - } - - try { - ISms iccISms = getISmsServiceOrThrow(); - if (iccISms != null) { - iccISms.sendTextForSubscriberWithOptions(getSubscriptionId(), - ActivityThread.currentPackageName(), destinationAddress, scAddress, text, - sentIntent, deliveryIntent, persistMessage, priority, expectMore, - validityPeriod); - } - } catch (RemoteException ex) { - // ignore it - } - } - - /** - * Send a text based SMS without writing it into the SMS Provider. - * - * <p>Requires Permission: - * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or the calling app has carrier - * privileges. - * </p> - * - * @see #sendTextMessage(String, String, String, PendingIntent, - * PendingIntent, int, boolean, int) - * @hide - */ - public void sendTextMessageWithoutPersisting( - String destinationAddress, String scAddress, String text, - PendingIntent sentIntent, PendingIntent deliveryIntent, int priority, - boolean expectMore, int validityPeriod) { - sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent, - false /* persistMessage */, priority, expectMore, validityPeriod); - } - - /** - * * Inject an SMS PDU into the android application framework. * * <p>Requires permission: {@link android.Manifest.permission#MODIFY_PHONE_STATE} or carrier @@ -653,140 +547,6 @@ public final class SmsManager { } /** - * Send a multi-part text based SMS with messaging options. The callee should have already - * divided the message into correctly sized parts by calling - * <code>divideMessage</code>. - * - * <p class="note"><strong>Note:</strong> Using this method requires that your app has the - * {@link android.Manifest.permission#SEND_SMS} permission.</p> - * - * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if - * <em>and only if</em> an app is not selected as the default SMS app, the system automatically - * writes messages sent using this method to the SMS Provider (the default SMS app is always - * responsible for writing its sent messages to the SMS Provider). For information about - * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p> - * - * @param destinationAddress the address to send the message to - * @param scAddress is the service center address or null to use - * the current default SMSC - * @param parts an <code>ArrayList</code> of strings that, in order, - * comprise the original message - * @param sentIntents if not null, an <code>ArrayList</code> of - * <code>PendingIntent</code>s (one for each message part) that is - * broadcast when the corresponding message part has been sent. - * The result code will be <code>Activity.RESULT_OK</code> for success, - * or one of these errors:<br> - * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> - * <code>RESULT_ERROR_RADIO_OFF</code><br> - * <code>RESULT_ERROR_NULL_PDU</code><br> - * For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include - * the extra "errorCode" containing a radio technology specific value, - * generally only useful for troubleshooting.<br> - * The per-application based SMS control checks sentIntent. If sentIntent - * is NULL the caller will be checked against all unknown applications, - * which cause smaller number of SMS to be sent in checking period. - * @param deliveryIntents if not null, an <code>ArrayList</code> of - * <code>PendingIntent</code>s (one for each message part) that is - * broadcast when the corresponding message part has been delivered - * to the recipient. The raw pdu of the status report is in the - * extended data ("pdu"). - * @param priority Priority level of the message - * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 - * --------------------------------- - * PRIORITY | Level of Priority - * --------------------------------- - * '00' | Normal - * '01' | Interactive - * '10' | Urgent - * '11' | Emergency - * ---------------------------------- - * Any Other values included Negative considered as Invalid Priority Indicator of the message. - * @param expectMore is a boolean to indicate the sending messages through same link or not. - * @param validityPeriod Validity Period of the message in mins. - * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. - * Validity Period(Minimum) -> 5 mins - * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). - * Any Other values included Negative considered as Invalid Validity Period of the message. - * - * @throws IllegalArgumentException if destinationAddress or data are empty - * {@hide} - */ - public void sendMultipartTextMessage( - String destinationAddress, String scAddress, ArrayList<String> parts, - ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents, - int priority, boolean expectMore, int validityPeriod) { - sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents, - deliveryIntents, true /* persistMessage*/); - } - - private void sendMultipartTextMessageInternal( - String destinationAddress, String scAddress, List<String> parts, - List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents, - boolean persistMessage, int priority, boolean expectMore, int validityPeriod) { - if (TextUtils.isEmpty(destinationAddress)) { - throw new IllegalArgumentException("Invalid destinationAddress"); - } - if (parts == null || parts.size() < 1) { - throw new IllegalArgumentException("Invalid message body"); - } - - if (priority < 0x00 || priority > 0x03) { - throw new IllegalArgumentException("Invalid priority"); - } - - if (validityPeriod < 0x05 || validityPeriod > 0x09b0a0) { - throw new IllegalArgumentException("Invalid validity period"); - } - - if (parts.size() > 1) { - try { - ISms iccISms = getISmsServiceOrThrow(); - if (iccISms != null) { - iccISms.sendMultipartTextForSubscriberWithOptions(getSubscriptionId(), - ActivityThread.currentPackageName(), destinationAddress, scAddress, - parts, sentIntents, deliveryIntents, persistMessage, priority, - expectMore, validityPeriod); - } - } catch (RemoteException ex) { - // ignore it - } - } else { - PendingIntent sentIntent = null; - PendingIntent deliveryIntent = null; - if (sentIntents != null && sentIntents.size() > 0) { - sentIntent = sentIntents.get(0); - } - if (deliveryIntents != null && deliveryIntents.size() > 0) { - deliveryIntent = deliveryIntents.get(0); - } - sendTextMessageInternal(destinationAddress, scAddress, parts.get(0), - sentIntent, deliveryIntent, persistMessage, priority, expectMore, - validityPeriod); - } - } - - /** - * Send a multi-part text based SMS without writing it into the SMS Provider. - * - * <p>Requires Permission: - * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or the calling app has carrier - * privileges. - * </p> - * - * @see #sendMultipartTextMessage(String, String, ArrayList, ArrayList, - * ArrayList, int, boolean, int) - * @hide - **/ - public void sendMultipartTextMessageWithoutPersisting( - String destinationAddress, String scAddress, List<String> parts, - List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents, - int priority, boolean expectMore, int validityPeriod) { - sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents, - deliveryIntents, false /* persistMessage*/, priority, expectMore, - validityPeriod); - } - - /** * Send a data based SMS to a specific application port. * * <p class="note"><strong>Note:</strong> Using this method requires that your app has the @@ -1249,7 +1009,7 @@ public final class SmsManager { * <code>getAllMessagesFromIcc</code> * @return <code>ArrayList</code> of <code>SmsMessage</code> objects. */ - private ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) { + private static ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) { ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>(); if (records != null) { int count = records.size(); @@ -1257,8 +1017,7 @@ public final class SmsManager { SmsRawData data = records.get(i); // List contains all records, including "free" records (null) if (data != null) { - SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes(), - getSubscriptionId()); + SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes()); if (sms != null) { messages.add(sms); } diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java index a5d67c60e40b..710eff0e0110 100644 --- a/telephony/java/android/telephony/SmsMessage.java +++ b/telephony/java/android/telephony/SmsMessage.java @@ -83,7 +83,10 @@ public class SmsMessage { public static final int MAX_USER_DATA_SEPTETS_WITH_HEADER = 153; /** @hide */ - @StringDef({FORMAT_3GPP, FORMAT_3GPP2}) + @StringDef(prefix = { "FORMAT_" }, value = { + FORMAT_3GPP, + FORMAT_3GPP2 + }) @Retention(RetentionPolicy.SOURCE) public @interface Format {} @@ -271,31 +274,6 @@ public class SmsMessage { } /** - * Create an SmsMessage from an SMS EF record. - * - * @param index Index of SMS record. This should be index in ArrayList - * returned by SmsManager.getAllMessagesFromSim + 1. - * @param data Record data. - * @param subId Subscription Id of the SMS - * @return An SmsMessage representing the record. - * - * @hide - */ - public static SmsMessage createFromEfRecord(int index, byte[] data, int subId) { - SmsMessageBase wrappedMessage; - - if (isCdmaVoice(subId)) { - wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromEfRecord( - index, data); - } else { - wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromEfRecord( - index, data); - } - - return wrappedMessage != null ? new SmsMessage(wrappedMessage) : null; - } - - /** * Get the TP-Layer-Length for the given SMS-SUBMIT PDU Basically, the * length in bytes (not hex chars) less the SMSC header * @@ -847,7 +825,6 @@ public class SmsMessage { int activePhone = TelephonyManager.getDefault().getCurrentPhoneType(subId); return (PHONE_TYPE_CDMA == activePhone); } - /** * Decide if the carrier supports long SMS. * {@hide} diff --git a/telephony/java/android/telephony/Telephony.java b/telephony/java/android/telephony/Telephony.java index d7b6142a5de6..942ea009f684 100644 --- a/telephony/java/android/telephony/Telephony.java +++ b/telephony/java/android/telephony/Telephony.java @@ -3342,6 +3342,12 @@ public final class Telephony { public static final String APN = "apn"; /** + * Prefix of Integrated Circuit Card Identifier. + * <P>Type: TEXT </P> + */ + public static final String ICCID_PREFIX = "iccid_prefix"; + + /** * User facing carrier name. * <P>Type: TEXT </P> */ diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 99fc9b33eba8..38819ce1d90b 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -6867,6 +6867,8 @@ public class TelephonyManager { * @return true if phone is in emergency callback mode * @hide */ + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode() { return getEmergencyCallbackMode(getSubId()); } diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl index a4eb424ab66e..fe37531c0611 100644 --- a/telephony/java/com/android/internal/telephony/ISms.aidl +++ b/telephony/java/com/android/internal/telephony/ISms.aidl @@ -187,57 +187,6 @@ interface ISms { in PendingIntent deliveryIntent, in boolean persistMessage); /** - * Send an SMS with options using Subscription Id. - * - * @param subId the subId on which the SMS has to be sent. - * @param destAddr the address to send the message to - * @param scAddr the SMSC to send the message through, or NULL for the - * default SMSC - * @param text the body of the message to send - * @param sentIntent if not NULL this <code>PendingIntent</code> is - * broadcast when the message is sucessfully sent, or failed. - * The result code will be <code>Activity.RESULT_OK<code> for success, - * or one of these errors:<br> - * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> - * <code>RESULT_ERROR_RADIO_OFF</code><br> - * <code>RESULT_ERROR_NULL_PDU</code><br> - * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include - * the extra "errorCode" containing a radio technology specific value, - * generally only useful for troubleshooting.<br> - * The per-application based SMS control checks sentIntent. If sentIntent - * is NULL the caller will be checked against all unknown applications, - * which cause smaller number of SMS to be sent in checking period. - * @param deliveryIntent if not NULL this <code>PendingIntent</code> is - * broadcast when the message is delivered to the recipient. The - * raw pdu of the status report is in the extended data ("pdu"). - * @param persistMessageForNonDefaultSmsApp whether the sent message should - * be automatically persisted in the SMS db. It only affects messages sent - * by a non-default SMS app. Currently only the carrier app can set this - * parameter to false to skip auto message persistence. - * @param priority Priority level of the message - * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 - * --------------------------------- - * PRIORITY | Level of Priority - * --------------------------------- - * '00' | Normal - * '01' | Interactive - * '10' | Urgent - * '11' | Emergency - * ---------------------------------- - * Any Other values included Negative considered as Invalid Priority Indicator of the message. - * @param expectMore is a boolean to indicate the sending message is multi segmented or not. - * @param validityPeriod Validity Period of the message in mins. - * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. - * Validity Period(Minimum) -> 5 mins - * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). - * Any Other values included Negative considered as Invalid Validity Period of the message. - */ - void sendTextForSubscriberWithOptions(in int subId, String callingPkg, in String destAddr, - in String scAddr, in String text, in PendingIntent sentIntent, - in PendingIntent deliveryIntent, in boolean persistMessageForNonDefaultSmsApp, - in int priority, in boolean expectMore, in int validityPeriod); - - /** * Inject an SMS PDU into the android platform. * * @param subId the subId on which the SMS has to be injected. @@ -285,56 +234,6 @@ interface ISms { in List<PendingIntent> deliveryIntents, in boolean persistMessageForNonDefaultSmsApp); /** - * Send a multi-part text based SMS with options using Subscription Id. - * - * @param subId the subId on which the SMS has to be sent. - * @param destinationAddress the address to send the message to - * @param scAddress is the service center address or null to use - * the current default SMSC - * @param parts an <code>ArrayList</code> of strings that, in order, - * comprise the original message - * @param sentIntents if not null, an <code>ArrayList</code> of - * <code>PendingIntent</code>s (one for each message part) that is - * broadcast when the corresponding message part has been sent. - * The result code will be <code>Activity.RESULT_OK<code> for success, - * or one of these errors: - * <code>RESULT_ERROR_GENERIC_FAILURE</code> - * <code>RESULT_ERROR_RADIO_OFF</code> - * <code>RESULT_ERROR_NULL_PDU</code>. - * @param deliveryIntents if not null, an <code>ArrayList</code> of - * <code>PendingIntent</code>s (one for each message part) that is - * broadcast when the corresponding message part has been delivered - * to the recipient. The raw pdu of the status report is in the - * extended data ("pdu"). - * @param persistMessageForNonDefaultSmsApp whether the sent message should - * be automatically persisted in the SMS db. It only affects messages sent - * by a non-default SMS app. Currently only the carrier app can set this - * parameter to false to skip auto message persistence. - * @param priority Priority level of the message - * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 - * --------------------------------- - * PRIORITY | Level of Priority - * --------------------------------- - * '00' | Normal - * '01' | Interactive - * '10' | Urgent - * '11' | Emergency - * ---------------------------------- - * Any Other values included Negative considered as Invalid Priority Indicator of the message. - * @param expectMore is a boolean to indicate the sending message is multi segmented or not. - * @param validityPeriod Validity Period of the message in mins. - * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. - * Validity Period(Minimum) -> 5 mins - * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). - * Any Other values included Negative considered as Invalid Validity Period of the message. - */ - void sendMultipartTextForSubscriberWithOptions(in int subId, String callingPkg, - in String destinationAddress, in String scAddress, in List<String> parts, - in List<PendingIntent> sentIntents, in List<PendingIntent> deliveryIntents, - in boolean persistMessageForNonDefaultSmsApp, in int priority, in boolean expectMore, - in int validityPeriod); - - /** * Enable reception of cell broadcast (SMS-CB) messages with the given * message identifier and RAN type. The RAN type specify this message ID * belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java index 14c5f4bebebb..7a53ef63e2a8 100644 --- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java @@ -99,15 +99,6 @@ public class SmsMessage extends SmsMessageBase { private static final int RETURN_NO_ACK = 0; private static final int RETURN_ACK = 1; - /** - * Supported priority modes for CDMA SMS messages - * (See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1) - */ - private static final int PRIORITY_NORMAL = 0x0; - private static final int PRIORITY_INTERACTIVE = 0x1; - private static final int PRIORITY_URGENT = 0x2; - private static final int PRIORITY_EMERGENCY = 0x3; - private SmsEnvelope mEnvelope; private BearerData mBearerData; @@ -220,26 +211,6 @@ public class SmsMessage extends SmsMessageBase { */ public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, String message, boolean statusReportRequested, SmsHeader smsHeader) { - return getSubmitPdu(scAddr, destAddr, message, statusReportRequested, smsHeader, -1); - } - - /** - * Get an SMS-SUBMIT PDU for a destination address and a message - * - * @param scAddr Service Centre address. Null means use default. - * @param destAddr Address of the recipient. - * @param message String representation of the message payload. - * @param statusReportRequested Indicates whether a report is requested for this message. - * @param smsHeader Array containing the data for the User Data Header, preceded - * by the Element Identifiers. - * @param priority Priority level of the message - * @return a <code>SubmitPdu</code> containing the encoded SC - * address, if applicable, and the encoded message. - * Returns null on encode error. - * @hide - */ - public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, String message, - boolean statusReportRequested, SmsHeader smsHeader, int priority) { /** * TODO(cleanup): Do we really want silent failure like this? @@ -253,7 +224,7 @@ public class SmsMessage extends SmsMessageBase { UserData uData = new UserData(); uData.payloadStr = message; uData.userDataHeader = smsHeader; - return privateGetSubmitPdu(destAddr, statusReportRequested, uData, priority); + return privateGetSubmitPdu(destAddr, statusReportRequested, uData); } /** @@ -311,22 +282,6 @@ public class SmsMessage extends SmsMessageBase { } /** - * Get an SMS-SUBMIT PDU for a data message to a destination address & port - * - * @param destAddr the address of the destination for the message - * @param userData the data for the message - * @param statusReportRequested Indicates whether a report is requested for this message. - * @param priority Priority level of the message - * @return a <code>SubmitPdu</code> containing the encoded SC - * address, if applicable, and the encoded message. - * Returns null on encode error. - */ - public static SubmitPdu getSubmitPdu(String destAddr, UserData userData, - boolean statusReportRequested, int priority) { - return privateGetSubmitPdu(destAddr, statusReportRequested, userData, priority); - } - - /** * Note: This function is a GSM specific functionality which is not supported in CDMA mode. */ @Override @@ -809,15 +764,6 @@ public class SmsMessage extends SmsMessageBase { */ private static SubmitPdu privateGetSubmitPdu(String destAddrStr, boolean statusReportRequested, UserData userData) { - return privateGetSubmitPdu(destAddrStr, statusReportRequested, userData, -1); - } - - /** - * Creates BearerData and Envelope from parameters for a Submit SMS. - * @return byte stream for SubmitPdu. - */ - private static SubmitPdu privateGetSubmitPdu(String destAddrStr, boolean statusReportRequested, - UserData userData, int priority) { /** * TODO(cleanup): give this function a more meaningful name. @@ -846,10 +792,6 @@ public class SmsMessage extends SmsMessageBase { bearerData.userAckReq = false; bearerData.readAckReq = false; bearerData.reportReq = false; - if (priority >= PRIORITY_NORMAL && priority <= PRIORITY_EMERGENCY) { - bearerData.priorityIndicatorSet = true; - bearerData.priority = priority; - } bearerData.userData = userData; diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java index 4f5bfa919135..1ca19e01d6c8 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java @@ -89,18 +89,6 @@ public class SmsMessage extends SmsMessageBase { private int mVoiceMailCount = 0; - private static final int VALIDITY_PERIOD_FORMAT_NONE = 0x00; - private static final int VALIDITY_PERIOD_FORMAT_ENHANCED = 0x01; - private static final int VALIDITY_PERIOD_FORMAT_RELATIVE = 0x02; - private static final int VALIDITY_PERIOD_FORMAT_ABSOLUTE = 0x03; - - //Validity Period min - 5 mins - private static final int VALIDITY_PERIOD_MIN = 5; - //Validity Period max - 63 weeks - private static final int VALIDITY_PERIOD_MAX = 635040; - - private static final int INVALID_VALIDITY_PERIOD = -1; - public static class SubmitPdu extends SubmitPduBase { } @@ -214,45 +202,6 @@ public class SmsMessage extends SmsMessageBase { } /** - * Get Encoded Relative Validty Period Value from Validity period in mins. - * - * @param validityPeriod Validity period in mins. - * - * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. - * ||relValidityPeriod (TP-VP) || || validityPeriod || - * - * 0 to 143 ---> (TP-VP + 1) x 5 minutes - * - * 144 to 167 ---> 12 hours + ((TP-VP -143) x 30 minutes) - * - * 168 to 196 ---> (TP-VP - 166) x 1 day - * - * 197 to 255 ---> (TP-VP - 192) x 1 week - * - * @return relValidityPeriod Encoded Relative Validity Period Value. - * @hide - */ - public static int getRelativeValidityPeriod(int validityPeriod) { - int relValidityPeriod = INVALID_VALIDITY_PERIOD; - - if (validityPeriod < VALIDITY_PERIOD_MIN || validityPeriod > VALIDITY_PERIOD_MAX) { - Rlog.e(LOG_TAG,"Invalid Validity Period" + validityPeriod); - return relValidityPeriod; - } - - if (validityPeriod <= 720) { - relValidityPeriod = (validityPeriod / 5) - 1; - } else if (validityPeriod <= 1440) { - relValidityPeriod = ((validityPeriod - 720) / 30) + 143; - } else if (validityPeriod <= 43200) { - relValidityPeriod = (validityPeriod / 1440) + 166; - } else if (validityPeriod <= 635040) { - relValidityPeriod = (validityPeriod / 10080) + 192; - } - return relValidityPeriod; - } - - /** * Get an SMS-SUBMIT PDU for a destination address and a message * * @param scAddress Service Centre address. Null means use default. @@ -287,29 +236,6 @@ public class SmsMessage extends SmsMessageBase { String destinationAddress, String message, boolean statusReportRequested, byte[] header, int encoding, int languageTable, int languageShiftTable) { - return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested, - header, encoding, languageTable, languageShiftTable, -1); - } - - /** - * Get an SMS-SUBMIT PDU for a destination address and a message using the - * specified encoding. - * - * @param scAddress Service Centre address. Null means use default. - * @param encoding Encoding defined by constants in - * com.android.internal.telephony.SmsConstants.ENCODING_* - * @param languageTable - * @param languageShiftTable - * @param validityPeriod Validity Period of the message in Minutes. - * @return a <code>SubmitPdu</code> containing the encoded SC - * address, if applicable, and the encoded message. - * Returns null on encode error. - * @hide - */ - public static SubmitPdu getSubmitPdu(String scAddress, - String destinationAddress, String message, - boolean statusReportRequested, byte[] header, int encoding, - int languageTable, int languageShiftTable, int validityPeriod) { // Perform null parameter checks. if (message == null || destinationAddress == null) { @@ -346,19 +272,8 @@ public class SmsMessage extends SmsMessageBase { } SubmitPdu ret = new SubmitPdu(); - - int validityPeriodFormat = VALIDITY_PERIOD_FORMAT_NONE; - int relativeValidityPeriod = INVALID_VALIDITY_PERIOD; - - // TP-Validity-Period-Format (TP-VPF) in 3GPP TS 23.040 V6.8.1 section 9.2.3.3 - //bit 4:3 = 10 - TP-VP field present - relative format - if((relativeValidityPeriod = getRelativeValidityPeriod(validityPeriod)) >= 0) { - validityPeriodFormat = VALIDITY_PERIOD_FORMAT_RELATIVE; - } - - byte mtiByte = (byte)(0x01 | (validityPeriodFormat << 0x03) | - (header != null ? 0x40 : 0x00)); - + // MTI = SMS-SUBMIT, UDHI = header != null + byte mtiByte = (byte)(0x01 | (header != null ? 0x40 : 0x00)); ByteArrayOutputStream bo = getSubmitPduHead( scAddress, destinationAddress, mtiByte, statusReportRequested, ret); @@ -423,11 +338,7 @@ public class SmsMessage extends SmsMessageBase { bo.write(0x08); } - if (validityPeriodFormat == VALIDITY_PERIOD_FORMAT_RELATIVE) { - // ( TP-Validity-Period - relative format) - bo.write(relativeValidityPeriod); - } - + // (no TP-Validity-Period) bo.write(userData, 0, userData.length); ret.encodedMessage = bo.toByteArray(); return ret; @@ -477,24 +388,6 @@ public class SmsMessage extends SmsMessageBase { } /** - * Get an SMS-SUBMIT PDU for a destination address and a message - * - * @param scAddress Service Centre address. Null means use default. - * @param destinationAddress the address of the destination for the message - * @param statusReportRequested staus report of the message Requested - * @param validityPeriod Validity Period of the message in Minutes. - * @return a <code>SubmitPdu</code> containing the encoded SC - * address, if applicable, and the encoded message. - * Returns null on encode error. - */ - public static SubmitPdu getSubmitPdu(String scAddress, - String destinationAddress, String message, - boolean statusReportRequested, int validityPeriod) { - return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested, - null, ENCODING_UNKNOWN, 0, 0, validityPeriod); - } - - /** * Get an SMS-SUBMIT PDU for a data message to a destination address & port * * @param scAddress Service Centre address. null == use default diff --git a/test-runner/Android.mk b/test-runner/Android.mk index 67f1354d52bc..706f6364ef8d 100644 --- a/test-runner/Android.mk +++ b/test-runner/Android.mk @@ -116,3 +116,6 @@ update-android-test-runner-api: $(ANDROID_TEST_RUNNER_OUTPUT_API_FILE) | $(ACP) $(hide) $(ACP) $(ANDROID_TEST_RUNNER_OUTPUT_REMOVED_API_FILE) $(ANDROID_TEST_RUNNER_REMOVED_API_FILE) endif # not TARGET_BUILD_APPS not TARGET_BUILD_PDK=true + +# additionally, build unit tests in a separate .apk +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/test-runner/tests/Android.mk b/test-runner/tests/Android.mk index 7ee047e47058..1a4f6d54fed7 100644 --- a/test-runner/tests/Android.mk +++ b/test-runner/tests/Android.mk @@ -25,8 +25,8 @@ include $(CLEAR_VARS) # LOCAL_MODULE_TAGS := tests -LOCAL_JAVA_LIBRARIES := android.test.runner -LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test +LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock +LOCAL_STATIC_JAVA_LIBRARIES := junit # Include all test java files. LOCAL_SRC_FILES := $(call all-java-files-under, src) diff --git a/tools/aapt2/LoadedApk.cpp b/tools/aapt2/LoadedApk.cpp index 33b5a8b2686d..20a9f417228c 100644 --- a/tools/aapt2/LoadedApk.cpp +++ b/tools/aapt2/LoadedApk.cpp @@ -57,31 +57,30 @@ std::unique_ptr<LoadedApk> LoadedApk::LoadApkFromPath(const StringPiece& path, I std::unique_ptr<LoadedApk> LoadedApk::LoadProtoApkFromFileCollection( const Source& source, unique_ptr<io::IFileCollection> collection, IDiagnostics* diag) { - io::IFile* table_file = collection->FindFile(kProtoResourceTablePath); - if (table_file == nullptr) { - diag->Error(DiagMessage(source) << "failed to find " << kProtoResourceTablePath); - return {}; - } + std::unique_ptr<ResourceTable> table; - std::unique_ptr<io::InputStream> in = table_file->OpenInputStream(); - if (in == nullptr) { - diag->Error(DiagMessage(source) << "failed to open " << kProtoResourceTablePath); - return {}; - } + io::IFile* table_file = collection->FindFile(kProtoResourceTablePath); + if (table_file != nullptr) { + pb::ResourceTable pb_table; + std::unique_ptr<io::InputStream> in = table_file->OpenInputStream(); + if (in == nullptr) { + diag->Error(DiagMessage(source) << "failed to open " << kProtoResourceTablePath); + return {}; + } - pb::ResourceTable pb_table; - io::ZeroCopyInputAdaptor adaptor(in.get()); - if (!pb_table.ParseFromZeroCopyStream(&adaptor)) { - diag->Error(DiagMessage(source) << "failed to read " << kProtoResourceTablePath); - return {}; - } + io::ZeroCopyInputAdaptor adaptor(in.get()); + if (!pb_table.ParseFromZeroCopyStream(&adaptor)) { + diag->Error(DiagMessage(source) << "failed to read " << kProtoResourceTablePath); + return {}; + } - std::string error; - std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>(); - if (!DeserializeTableFromPb(pb_table, collection.get(), table.get(), &error)) { - diag->Error(DiagMessage(source) - << "failed to deserialize " << kProtoResourceTablePath << ": " << error); - return {}; + std::string error; + table = util::make_unique<ResourceTable>(); + if (!DeserializeTableFromPb(pb_table, collection.get(), table.get(), &error)) { + diag->Error(DiagMessage(source) + << "failed to deserialize " << kProtoResourceTablePath << ": " << error); + return {}; + } } io::IFile* manifest_file = collection->FindFile(kAndroidManifestPath); @@ -103,6 +102,7 @@ std::unique_ptr<LoadedApk> LoadedApk::LoadProtoApkFromFileCollection( return {}; } + std::string error; std::unique_ptr<xml::XmlResource> manifest = DeserializeXmlResourceFromPb(pb_node, &error); if (manifest == nullptr) { diag->Error(DiagMessage(source) @@ -115,24 +115,21 @@ std::unique_ptr<LoadedApk> LoadedApk::LoadProtoApkFromFileCollection( std::unique_ptr<LoadedApk> LoadedApk::LoadBinaryApkFromFileCollection( const Source& source, unique_ptr<io::IFileCollection> collection, IDiagnostics* diag) { - io::IFile* table_file = collection->FindFile(kApkResourceTablePath); - if (table_file == nullptr) { - diag->Error(DiagMessage(source) << "failed to find " << kApkResourceTablePath); - - return {}; - } + std::unique_ptr<ResourceTable> table; - std::unique_ptr<io::IData> data = table_file->OpenAsData(); - if (data == nullptr) { - diag->Error(DiagMessage(source) << "failed to open " << kApkResourceTablePath); - return {}; - } - - std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>(); - BinaryResourceParser parser(diag, table.get(), source, data->data(), data->size(), - collection.get()); - if (!parser.Parse()) { - return {}; + io::IFile* table_file = collection->FindFile(kApkResourceTablePath); + if (table_file != nullptr) { + table = util::make_unique<ResourceTable>(); + std::unique_ptr<io::IData> data = table_file->OpenAsData(); + if (data == nullptr) { + diag->Error(DiagMessage(source) << "failed to open " << kApkResourceTablePath); + return {}; + } + BinaryResourceParser parser(diag, table.get(), source, data->data(), data->size(), + collection.get()); + if (!parser.Parse()) { + return {}; + } } io::IFile* manifest_file = collection->FindFile(kAndroidManifestPath); diff --git a/tools/aapt2/cmd/Convert.cpp b/tools/aapt2/cmd/Convert.cpp index 2bd2405612e3..964dacfeafef 100644 --- a/tools/aapt2/cmd/Convert.cpp +++ b/tools/aapt2/cmd/Convert.cpp @@ -64,36 +64,38 @@ bool ConvertApk(IAaptContext* context, unique_ptr<LoadedApk> apk, IApkSerializer return false; } - // Resource table - if (!serializer->SerializeTable(apk->GetResourceTable(), writer)) { - context->GetDiagnostics()->Error(DiagMessage(apk->GetSource()) - << "failed to serialize the resource table"); - return false; - } + if (apk->GetResourceTable() != nullptr) { + // Resource table + if (!serializer->SerializeTable(apk->GetResourceTable(), writer)) { + context->GetDiagnostics()->Error(DiagMessage(apk->GetSource()) + << "failed to serialize the resource table"); + return false; + } - // Resources - for (const auto& package : apk->GetResourceTable()->packages) { - for (const auto& type : package->types) { - for (const auto& entry : type->entries) { - for (const auto& config_value : entry->values) { - const FileReference* file = ValueCast<FileReference>(config_value->value.get()); - if (file != nullptr) { - if (file->file == nullptr) { - context->GetDiagnostics()->Error(DiagMessage(apk->GetSource()) - << "no file associated with " << *file); - return false; - } - - if (!serializer->SerializeFile(file, writer)) { - context->GetDiagnostics()->Error(DiagMessage(apk->GetSource()) - << "failed to serialize file " << *file->path); - return false; - } - } // file - } // config_value - } // entry - } // type - } // package + // Resources + for (const auto& package : apk->GetResourceTable()->packages) { + for (const auto& type : package->types) { + for (const auto& entry : type->entries) { + for (const auto& config_value : entry->values) { + const FileReference* file = ValueCast<FileReference>(config_value->value.get()); + if (file != nullptr) { + if (file->file == nullptr) { + context->GetDiagnostics()->Error(DiagMessage(apk->GetSource()) + << "no file associated with " << *file); + return false; + } + + if (!serializer->SerializeFile(file, writer)) { + context->GetDiagnostics()->Error(DiagMessage(apk->GetSource()) + << "failed to serialize file " << *file->path); + return false; + } + } // file + } // config_value + } // entry + } // type + } // package + } // Other files std::unique_ptr<io::IFileCollectionIterator> iterator = apk->GetFileCollection()->Iterator(); diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index 13dd93e83b64..d782de55f66a 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -1069,25 +1069,29 @@ class LinkCommand { bool WriteJavaFile(ResourceTable* table, const StringPiece& package_name_to_generate, const StringPiece& out_package, const JavaClassGeneratorOptions& java_options, const Maybe<std::string>& out_text_symbols_path = {}) { - if (!options_.generate_java_class_path) { + if (!options_.generate_java_class_path && !out_text_symbols_path) { return true; } - std::string out_path = options_.generate_java_class_path.value(); - file::AppendPath(&out_path, file::PackageToPath(out_package)); - if (!file::mkdirs(out_path)) { - context_->GetDiagnostics()->Error(DiagMessage() << "failed to create directory '" << out_path - << "'"); - return false; - } + std::string out_path; + std::unique_ptr<io::FileOutputStream> fout; + if (options_.generate_java_class_path) { + out_path = options_.generate_java_class_path.value(); + file::AppendPath(&out_path, file::PackageToPath(out_package)); + if (!file::mkdirs(out_path)) { + context_->GetDiagnostics()->Error(DiagMessage() + << "failed to create directory '" << out_path << "'"); + return false; + } - file::AppendPath(&out_path, "R.java"); + file::AppendPath(&out_path, "R.java"); - io::FileOutputStream fout(out_path); - if (fout.HadError()) { - context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path - << "': " << fout.GetError()); - return false; + fout = util::make_unique<io::FileOutputStream>(out_path); + if (fout->HadError()) { + context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path + << "': " << fout->GetError()); + return false; + } } std::unique_ptr<io::FileOutputStream> fout_text; @@ -1102,18 +1106,11 @@ class LinkCommand { } JavaClassGenerator generator(context_, table, java_options); - if (!generator.Generate(package_name_to_generate, out_package, &fout, fout_text.get())) { + if (!generator.Generate(package_name_to_generate, out_package, fout.get(), fout_text.get())) { context_->GetDiagnostics()->Error(DiagMessage(out_path) << generator.GetError()); return false; } - fout.Flush(); - - if (fout.HadError()) { - context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path - << "': " << fout.GetError()); - return false; - } return true; } @@ -1934,7 +1931,7 @@ class LinkCommand { return 1; } - if (options_.generate_java_class_path) { + if (options_.generate_java_class_path || options_.generate_text_symbols_path) { if (!GenerateJavaClasses()) { return 1; } diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp index 1bdb762528b6..eaadfd82629e 100644 --- a/tools/aapt2/cmd/Optimize.cpp +++ b/tools/aapt2/cmd/Optimize.cpp @@ -327,7 +327,6 @@ int Optimize(const std::vector<StringPiece>& args) { Maybe<std::string> config_path; Maybe<std::string> whitelist_path; Maybe<std::string> target_densities; - Maybe<std::string> target_abis; std::vector<std::string> configs; std::vector<std::string> split_args; std::unordered_set<std::string> kept_artifacts; @@ -349,12 +348,6 @@ int Optimize(const std::vector<StringPiece>& args) { "Path to the whitelist.cfg file containing whitelisted resources \n" "whose names should not be altered in final resource tables.", &whitelist_path) - .OptionalFlag( - "--target-abis", - "Comma separated list of the CPU ABIs that the APK will be optimized for.\n" - "All the native libraries that would be unused on devices of the given ABIs will \n" - "be removed from the APK.", - &target_abis) .OptionalFlagList("-c", "Comma separated list of configurations to include. The default\n" "is all configurations.", diff --git a/tools/aapt2/configuration/ConfigurationParser.cpp b/tools/aapt2/configuration/ConfigurationParser.cpp index b99240f0a40a..852ff176ed7d 100644 --- a/tools/aapt2/configuration/ConfigurationParser.cpp +++ b/tools/aapt2/configuration/ConfigurationParser.cpp @@ -519,14 +519,22 @@ ConfigurationParser::ActionHandler ConfigurationParser::android_sdk_group_handle } else { AndroidSdk entry; for (const auto& attr : child->attributes) { + Maybe<int>* target = nullptr; if (attr.name == "minSdkVersion") { - entry.min_sdk_version = ResourceUtils::ParseSdkVersion(attr.value); + target = &entry.min_sdk_version; } else if (attr.name == "targetSdkVersion") { - entry.target_sdk_version = ResourceUtils::ParseSdkVersion(attr.value); + target = &entry.target_sdk_version; } else if (attr.name == "maxSdkVersion") { - entry.max_sdk_version = ResourceUtils::ParseSdkVersion(attr.value); + target = &entry.max_sdk_version; } else { diag->Warn(DiagMessage() << "Unknown attribute: " << attr.name << " = " << attr.value); + continue; + } + + *target = ResourceUtils::ParseSdkVersion(attr.value); + if (!*target) { + diag->Error(DiagMessage() << "Invalid attribute: " << attr.name << " = " << attr.value); + valid = false; } } diff --git a/tools/aapt2/configuration/ConfigurationParser_test.cpp b/tools/aapt2/configuration/ConfigurationParser_test.cpp index afa155f46eb9..f7153c822bbc 100644 --- a/tools/aapt2/configuration/ConfigurationParser_test.cpp +++ b/tools/aapt2/configuration/ConfigurationParser_test.cpp @@ -18,8 +18,10 @@ #include <string> +#include "android-base/stringprintf.h" #include "androidfw/ResourceTypes.h" +#include "SdkConstants.h" #include "test/Test.h" #include "xml/XmlDom.h" @@ -35,18 +37,19 @@ void PrintTo(const AndroidSdk& sdk, std::ostream* os) { namespace { +using ::aapt::configuration::Abi; +using ::aapt::configuration::AndroidManifest; +using ::aapt::configuration::AndroidSdk; +using ::aapt::configuration::Artifact; +using ::aapt::configuration::DeviceFeature; +using ::aapt::configuration::GlTexture; +using ::aapt::configuration::Locale; +using ::aapt::configuration::PostProcessingConfiguration; +using ::aapt::xml::Element; +using ::aapt::xml::NodeCast; using ::android::ResTable_config; -using configuration::Abi; -using configuration::AndroidSdk; -using configuration::Artifact; -using configuration::PostProcessingConfiguration; -using configuration::DeviceFeature; -using configuration::GlTexture; -using configuration::Locale; -using configuration::AndroidManifest; +using ::android::base::StringPrintf; using ::testing::ElementsAre; -using xml::Element; -using xml::NodeCast; constexpr const char* kValidConfig = R"(<?xml version="1.0" encoding="utf-8" ?> <post-process xmlns="http://schemas.android.com/tools/aapt"> @@ -421,17 +424,106 @@ TEST_F(ConfigurationParserTest, AndroidSdkGroupAction) { ASSERT_EQ(sdk, out); } +TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_SingleVersion) { + { + static constexpr const char* xml = R"xml( + <android-sdk-group label="v19"> + <android-sdk minSdkVersion="19"></android-sdk> + </android-sdk-group>)xml"; + + auto doc = test::BuildXmlDom(xml); + + PostProcessingConfiguration config; + bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + ASSERT_TRUE(ok); + + ASSERT_EQ(1ul, config.android_sdk_groups.size()); + ASSERT_EQ(1u, config.android_sdk_groups.count("v19")); + + auto& out = config.android_sdk_groups["v19"]; + EXPECT_EQ(19, out.min_sdk_version.value()); + EXPECT_FALSE(out.max_sdk_version); + EXPECT_FALSE(out.target_sdk_version); + } + + { + static constexpr const char* xml = R"xml( + <android-sdk-group label="v19"> + <android-sdk maxSdkVersion="19"></android-sdk> + </android-sdk-group>)xml"; + + auto doc = test::BuildXmlDom(xml); + + PostProcessingConfiguration config; + bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + ASSERT_TRUE(ok); + + ASSERT_EQ(1ul, config.android_sdk_groups.size()); + ASSERT_EQ(1u, config.android_sdk_groups.count("v19")); + + auto& out = config.android_sdk_groups["v19"]; + EXPECT_EQ(19, out.max_sdk_version.value()); + EXPECT_FALSE(out.min_sdk_version); + EXPECT_FALSE(out.target_sdk_version); + } + + { + static constexpr const char* xml = R"xml( + <android-sdk-group label="v19"> + <android-sdk targetSdkVersion="19"></android-sdk> + </android-sdk-group>)xml"; + + auto doc = test::BuildXmlDom(xml); + + PostProcessingConfiguration config; + bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + ASSERT_TRUE(ok); + + ASSERT_EQ(1ul, config.android_sdk_groups.size()); + ASSERT_EQ(1u, config.android_sdk_groups.count("v19")); + + auto& out = config.android_sdk_groups["v19"]; + EXPECT_EQ(19, out.target_sdk_version.value()); + EXPECT_FALSE(out.min_sdk_version); + EXPECT_FALSE(out.max_sdk_version); + } +} + +TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_InvalidVersion) { + static constexpr const char* xml = R"xml( + <android-sdk-group label="v19"> + <android-sdk + minSdkVersion="v19" + targetSdkVersion="v24" + maxSdkVersion="v25"> + <manifest> + <!--- manifest additions here XSLT? TODO --> + </manifest> + </android-sdk> + </android-sdk-group>)xml"; + + auto doc = test::BuildXmlDom(xml); + + PostProcessingConfiguration config; + bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + ASSERT_FALSE(ok); +} + TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_NonNumeric) { static constexpr const char* xml = R"xml( <android-sdk-group label="P"> <android-sdk - minSdkVersion="M" - targetSdkVersion="P" - maxSdkVersion="P"> + minSdkVersion="25" + targetSdkVersion="%s" + maxSdkVersion="%s"> </android-sdk> </android-sdk-group>)xml"; - auto doc = test::BuildXmlDom(xml); + const auto& dev_sdk = GetDevelopmentSdkCodeNameAndVersion(); + const char* codename = dev_sdk.first.data(); + const ApiVersion& version = dev_sdk.second; + + auto doc = test::BuildXmlDom(StringPrintf(xml, codename, codename)); PostProcessingConfiguration config; bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); @@ -443,9 +535,9 @@ TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_NonNumeric) { auto& out = config.android_sdk_groups["P"]; AndroidSdk sdk; - sdk.min_sdk_version = {}; // Only the latest development version is supported. - sdk.target_sdk_version = 28; - sdk.max_sdk_version = 28; + sdk.min_sdk_version = 25; + sdk.target_sdk_version = version; + sdk.max_sdk_version = version; ASSERT_EQ(sdk, out); } diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp index 9861770083a2..8c8c2549609a 100644 --- a/tools/aapt2/java/JavaClassGenerator.cpp +++ b/tools/aapt2/java/JavaClassGenerator.cpp @@ -272,7 +272,7 @@ void JavaClassGenerator::ProcessStyleable(const ResourceNameRef& name, const Res // Build the JavaDoc comment for the Styleable array. This has references to child attributes // and what possible values can be used for them. const size_t attr_count = sorted_attributes.size(); - if (attr_count > 0) { + if (out_class_def != nullptr && attr_count > 0) { std::stringstream styleable_comment; if (!styleable.GetComment().empty()) { styleable_comment << styleable.GetComment() << "\n"; @@ -356,54 +356,56 @@ void JavaClassGenerator::ProcessStyleable(const ResourceNameRef& name, const Res continue; } - StringPiece comment = styleable_attr.attr_ref->GetComment(); - if (styleable_attr.symbol.value().attribute && comment.empty()) { - comment = styleable_attr.symbol.value().attribute->GetComment(); - } + if (out_class_def != nullptr) { + StringPiece comment = styleable_attr.attr_ref->GetComment(); + if (styleable_attr.symbol.value().attribute && comment.empty()) { + comment = styleable_attr.symbol.value().attribute->GetComment(); + } - if (comment.contains("@removed")) { - // Removed attributes are public but hidden from the documentation, so - // don't emit them as part of the class documentation. - continue; - } + if (comment.contains("@removed")) { + // Removed attributes are public but hidden from the documentation, so + // don't emit them as part of the class documentation. + continue; + } - const ResourceName& attr_name = styleable_attr.attr_ref->name.value(); + const ResourceName& attr_name = styleable_attr.attr_ref->name.value(); - StringPiece package_name = attr_name.package; - if (package_name.empty()) { - package_name = context_->GetCompilationPackage(); - } + StringPiece package_name = attr_name.package; + if (package_name.empty()) { + package_name = context_->GetCompilationPackage(); + } - std::unique_ptr<IntMember> index_member = util::make_unique<IntMember>( - sorted_attributes[i].field_name, static_cast<uint32_t>(i)); + std::unique_ptr<IntMember> index_member = + util::make_unique<IntMember>(sorted_attributes[i].field_name, static_cast<uint32_t>(i)); + + AnnotationProcessor* attr_processor = index_member->GetCommentBuilder(); + + if (!comment.empty()) { + attr_processor->AppendComment("<p>\n@attr description"); + attr_processor->AppendComment(comment); + } else { + std::stringstream default_comment; + default_comment << "<p>This symbol is the offset where the " + << "{@link " << package_name << ".R.attr#" + << TransformToFieldName(attr_name.entry) << "}\n" + << "attribute's value can be found in the " + << "{@link #" << array_field_name << "} array."; + attr_processor->AppendComment(default_comment.str()); + } - AnnotationProcessor* attr_processor = index_member->GetCommentBuilder(); + attr_processor->AppendNewLine(); + AddAttributeFormatDoc(attr_processor, styleable_attr.symbol.value().attribute.get()); + attr_processor->AppendNewLine(); + attr_processor->AppendComment( + StringPrintf("@attr name %s:%s", package_name.data(), attr_name.entry.data())); - if (!comment.empty()) { - attr_processor->AppendComment("<p>\n@attr description"); - attr_processor->AppendComment(comment); - } else { - std::stringstream default_comment; - default_comment << "<p>This symbol is the offset where the " - << "{@link " << package_name << ".R.attr#" - << TransformToFieldName(attr_name.entry) << "}\n" - << "attribute's value can be found in the " - << "{@link #" << array_field_name << "} array."; - attr_processor->AppendComment(default_comment.str()); + out_class_def->AddMember(std::move(index_member)); } - attr_processor->AppendNewLine(); - AddAttributeFormatDoc(attr_processor, styleable_attr.symbol.value().attribute.get()); - attr_processor->AppendNewLine(); - attr_processor->AppendComment( - StringPrintf("@attr name %s:%s", package_name.data(), attr_name.entry.data())); - if (r_txt_printer != nullptr) { r_txt_printer->Println( StringPrintf("int styleable %s %zd", sorted_attributes[i].field_name.c_str(), i)); } - - out_class_def->AddMember(std::move(index_member)); } // If there is a rewrite method to generate, add the statements that rewrite package IDs @@ -434,31 +436,33 @@ void JavaClassGenerator::ProcessResource(const ResourceNameRef& name, const Reso } const std::string field_name = TransformToFieldName(name.entry); - std::unique_ptr<ResourceMember> resource_member = - util::make_unique<ResourceMember>(field_name, real_id); + if (out_class_def != nullptr) { + std::unique_ptr<ResourceMember> resource_member = + util::make_unique<ResourceMember>(field_name, real_id); - // Build the comments and annotations for this entry. - AnnotationProcessor* processor = resource_member->GetCommentBuilder(); + // Build the comments and annotations for this entry. + AnnotationProcessor* processor = resource_member->GetCommentBuilder(); - // Add the comments from any <public> tags. - if (entry.symbol_status.state != SymbolState::kUndefined) { - processor->AppendComment(entry.symbol_status.comment); - } + // Add the comments from any <public> tags. + if (entry.symbol_status.state != SymbolState::kUndefined) { + processor->AppendComment(entry.symbol_status.comment); + } - // Add the comments from all configurations of this entry. - for (const auto& config_value : entry.values) { - processor->AppendComment(config_value->value->GetComment()); - } + // Add the comments from all configurations of this entry. + for (const auto& config_value : entry.values) { + processor->AppendComment(config_value->value->GetComment()); + } - // If this is an Attribute, append the format Javadoc. - if (!entry.values.empty()) { - if (Attribute* attr = ValueCast<Attribute>(entry.values.front()->value.get())) { - // We list out the available values for the given attribute. - AddAttributeFormatDoc(processor, attr); + // If this is an Attribute, append the format Javadoc. + if (!entry.values.empty()) { + if (Attribute* attr = ValueCast<Attribute>(entry.values.front()->value.get())) { + // We list out the available values for the given attribute. + AddAttributeFormatDoc(processor, attr); + } } - } - out_class_def->AddMember(std::move(resource_member)); + out_class_def->AddMember(std::move(resource_member)); + } if (r_txt_printer != nullptr) { r_txt_printer->Print("int ") @@ -576,7 +580,7 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, } // Generate an onResourcesLoaded() callback if requested. - if (options_.rewrite_callback_options) { + if (out != nullptr && options_.rewrite_callback_options) { rewrite_method = util::make_unique<MethodDefinition>("public static void onResourcesLoaded(int p)"); for (const std::string& package_to_callback : @@ -597,8 +601,12 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, const bool force_creation_if_empty = (options_.types == JavaClassGeneratorOptions::SymbolTypes::kPublic); - std::unique_ptr<ClassDefinition> class_def = util::make_unique<ClassDefinition>( - to_string(type->type), ClassQualifier::kStatic, force_creation_if_empty); + std::unique_ptr<ClassDefinition> class_def; + if (out != nullptr) { + class_def = util::make_unique<ClassDefinition>( + to_string(type->type), ClassQualifier::kStatic, force_creation_if_empty); + } + if (!ProcessType(package_name_to_generate, *package, *type, class_def.get(), rewrite_method.get(), r_txt_printer.get())) { return false; @@ -615,16 +623,17 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, } } - if (type->type == ResourceType::kStyleable && + if (out != nullptr && type->type == ResourceType::kStyleable && options_.types == JavaClassGeneratorOptions::SymbolTypes::kPublic) { // When generating a public R class, we don't want Styleable to be part // of the API. It is only emitted for documentation purposes. class_def->GetCommentBuilder()->AppendComment("@doconly"); } - AppendJavaDocAnnotations(options_.javadoc_annotations, class_def->GetCommentBuilder()); - - r_class.AddMember(std::move(class_def)); + if (out != nullptr) { + AppendJavaDocAnnotations(options_.javadoc_annotations, class_def->GetCommentBuilder()); + r_class.AddMember(std::move(class_def)); + } } } @@ -632,8 +641,10 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, r_class.AddMember(std::move(rewrite_method)); } - AppendJavaDocAnnotations(options_.javadoc_annotations, r_class.GetCommentBuilder()); - ClassDefinition::WriteJavaFile(&r_class, out_package_name, options_.use_final, out); + if (out != nullptr) { + AppendJavaDocAnnotations(options_.javadoc_annotations, r_class.GetCommentBuilder()); + ClassDefinition::WriteJavaFile(&r_class, out_package_name, options_.use_final, out); + } return true; } diff --git a/tools/aapt2/optimize/MultiApkGenerator.cpp b/tools/aapt2/optimize/MultiApkGenerator.cpp index da3b8792be69..e2d738aec5a2 100644 --- a/tools/aapt2/optimize/MultiApkGenerator.cpp +++ b/tools/aapt2/optimize/MultiApkGenerator.cpp @@ -17,6 +17,7 @@ #include "MultiApkGenerator.h" #include <algorithm> +#include <regex> #include <string> #include "androidfw/StringPiece.h" @@ -125,6 +126,16 @@ class ContextWrapper : public IAaptContext { int min_sdk_ = -1; }; +class SignatureFilter : public IPathFilter { + bool Keep(const std::string& path) override { + static std::regex signature_regex(R"regex(^META-INF/.*\.(RSA|DSA|EC|SF)$)regex"); + if (std::regex_search(path, signature_regex)) { + return false; + } + return !(path == "META-INF/MANIFEST.MF"); + } +}; + MultiApkGenerator::MultiApkGenerator(LoadedApk* apk, IAaptContext* context) : apk_(apk), context_(context) { } @@ -209,6 +220,7 @@ bool MultiApkGenerator::FromBaseApk(const MultiApkGeneratorOptions& options) { diag.Note(DiagMessage() << "Writing output: " << out); } + filters.AddFilter(util::make_unique<SignatureFilter>()); if (!apk_->WriteToArchive(&wrapped_context, table.get(), options.table_flattener_options, &filters, writer.get(), manifest.get())) { return false; |